List of commits:
Subject Hash Author Date (UTC)
Checkpoint before non-storing tokens 14b76a10a18045ae9d6b71614772ca2ba0653034 Catalin(ux) M. BOIE 2014-12-20 09:03:38
Checkpoint a87a60265dd93710118fc92b13121b7d7296823b Catalin(ux) M. BOIE 2014-12-16 21:19:16
Checkpoint c99a539501f24a82fb890a7ef59e2d97517246c5 Catalin(ux) M. BOIE 2014-12-10 21:25:25
Checkpoint 408ea6e114460b413daca5e96d1551ef04080a04 Catalin(ux) M. BOIE 2014-12-09 17:18:17
Checkpoint 70b59e41caa4a49a3f6580e104da0c8e6cec8658 Catalin(ux) M. BOIE 2014-11-20 04:42:44
Checkpoint 954ee41b76dcfe6920ebd36bd81453bc26276890 Catalin(ux) M. BOIE 2014-11-14 22:37:07
Checkpoint 91a81af5a65c575fa1d61ac9cc5eb759b746a9ed Catalin(ux) M. BOIE 2014-10-29 04:19:22
Checkpoint 8aa274777cd39834ea3467399ec8b072a136e525 Catalin(ux) M. BOIE 2014-10-24 20:41:00
Checkpoint af5c3e9e60264219565f682fa909b9f829e0fa9d Catalin(ux) M. BOIE 2014-10-23 19:50:16
Checkpoint c4115b92bd328d7b6931d2854f63d0fe7e685aad Catalin(ux) M. BOIE 2014-10-09 17:35:54
Checkpoint d27058ed0323fbe336584a1155c4c02489ee641d Catalin(ux) M. BOIE 2014-10-08 18:52:24
WIP c393b624a4544dd58b7c3a6c9e09bf5d94fba6c1 Catalin(ux) M. BOIE 2014-09-23 03:01:33
Checkpoint: added path rights and fixed mail sending 24aa6660e6ee2530739545da09869b116c77df3b Catalin(ux) M. BOIE 2014-09-07 07:12:43
Checkpoint c769943b7cd003725a18731a1723616010582d50 Catalin(ux) M. BOIE 2014-09-06 05:43:17
Checkpoint after a lot of pause 53c17f78a3d70e22165de311ff56b094cb3b1096 Catalin(ux) M. BOIE 2014-04-14 18:23:27
Checkpoint - mostly fixes for tests and switch to sql_params 28830fcf28cf8f3ae0f59bf1205281820df1307a Catalin(ux) M. BOIE 2013-07-16 19:42:15
Bulk changes all over the place. 69bd7667ac66a02ae3734ddb2f1eb8eec526e3bf Catalin(ux) M. BOIE 2013-04-21 06:40:27
Fixed repo search: ui['admin'] may not be defined 48794821cb9a4ea8fa793144256ac916b1554bf2 Catalin(ux) M. BOIE 2013-02-18 19:37:31
Several changes. Bump version to 0.18 57269df7b88cd6cbb0c2569c6e14d94887c6ca40 Catalin(ux) M. BOIE 2013-02-17 10:10:48
Bump the version 753abba3b1f6caac8f96d801e5a5d1786023aa2f Catalin(ux) M. BOIE 2013-02-05 19:40:38
Commit 14b76a10a18045ae9d6b71614772ca2ba0653034 - Checkpoint before non-storing tokens
Author: Catalin(ux) M. BOIE
Author date (UTC): 2014-12-20 09:03
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2014-12-20 09:03
Parent(s): a87a60265dd93710118fc92b13121b7d7296823b
Signing key:
Tree: a0aaf599ccf216a479150034832b504b55b14a9a
File Lines added Lines deleted
TODO 33 0
inc/cache.inc.php 3 0
inc/struct.inc.php 2 1
inc/token.inc.php 5 4
tests/token.php 34 12
File TODO changed (mode: 100644) (index 59dfe3d..a503461)
... ... e-mail to him. Or I may comment on LWN or "PEP 474".
7 7 Find a way to distribute this code and a way to support it in rg. Find a way to distribute this code and a way to support it in rg.
8 8 Probably I will allow only one plan (Friends) till they all create Probably I will allow only one plan (Friends) till they all create
9 9 accounts. After this, I will remove this plan? accounts. After this, I will remove this plan?
10 [ ] CSRF for logout. Seems is not so easy because I need to generate a token
11 all the time to embed it in the logout link. Another possibility
12 is to have a form on the logout page. But some people probably will
13 assume that pressing the logout link is enough and will not press
14 the logout _button_. A signed token is enough, if I prepare it special
15 for logout. It is important to work only there. And, I can embed it in
16 the link.
17 Anyway, I can link all tokens with the forms and I can store them in
18 db when they are used, so we cannot use them anymore. This way I do not
19 have to save them in database at generation time.
20 What is the problem with the token?! Double post? And using same token
21 for two forms?
22 [ ] If email is not confirmed, do not send e-mail!
23 [ ] Now, we gen generate tokens without storing in database, and store tokens
24 in db only after they are used. In rg_token_valid, we will check if it
25 was already used, after we check the signing.
26 generate_token
27 user post form
28 we insert it in db => ok
29 user post it again
30 we insert it in db => get error!
31 this means was already used it
32 abort
33 continue work
34 What I have to change:
35 - rg_token_get must return a signed token. Maybe we add the form id to
36 the equation.
37 - rg_token_valid: we insert it in db as used, return FALSE if we get
38 an error. We need to know if db failed or we could not
39 insert because of already present key
40 - get rid of tokens.used field. What about expiration?
41
10 42 [ ] [ ]
11 43
12 44 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
45 [ ] Check cache socket is protected agains other users.
13 46 [ ] Ce se intimpla daca un atacator seteaza un cookie pe .com, de exemplu. [ ] Ce se intimpla daca un atacator seteaza un cookie pe .com, de exemplu.
14 47 El se va trimite si pe rocketgit.com. Deci, daca user-ul viziteaza site-ul El se va trimite si pe rocketgit.com. Deci, daca user-ul viziteaza site-ul
15 48 atacatorului, se seteaza acest cookie, care apoi va fi trimis catre rg.com. atacatorului, se seteaza acest cookie, care apoi va fi trimis catre rg.com.
File inc/cache.inc.php changed (mode: 100644) (index 77c1962..188a1e2)
... ... function rg_cache_unset($ns_var)
469 469 break; break;
470 470 } }
471 471
472 if (strncmp($ret, "NOT_FOUND", 9) == 0)
473 break;
474
472 475 // TODO: return old value? // TODO: return old value?
473 476 if (strncmp($ret, "OK", 2) != 0) { if (strncmp($ret, "OK", 2) != 0) {
474 477 rg_internal_error("Invalid answer: $ret"); rg_internal_error("Invalid answer: $ret");
File inc/struct.inc.php changed (mode: 100644) (index 8332f23..27bbb3d)
... ... $rg_sql_struct[30]['tables'] = array();
399 399 $rg_sql_struct[30]['other'] = array( $rg_sql_struct[30]['other'] = array(
400 400 "events.fail" => "ALTER TABLE events ADD fail SMALLINT NOT NULL DEFAULT 0", "events.fail" => "ALTER TABLE events ADD fail SMALLINT NOT NULL DEFAULT 0",
401 401 "events.tries" => "ALTER TABLE events ADD tries SMALLINT NOT NULL DEFAULT 0", "events.tries" => "ALTER TABLE events ADD tries SMALLINT NOT NULL DEFAULT 0",
402 "events.next_try" => "ALTER TABLE events ADD next_try INTEGER NOT NULL DEFAULT 0"
402 "events.next_try" => "ALTER TABLE events ADD next_try INTEGER NOT NULL DEFAULT 0",
403 "tokens.used" => "ALTER TABLE tokens ADD used SMALLINT NOT NULL DEFAULT 0"
403 404 ); );
404 405
405 406
File inc/token.inc.php changed (mode: 100644) (index 1b8f04b..ecf6f7e)
... ... function rg_token_valid($db, $rg)
138 138 $rand = substr($rg['token'], 0, 16); $rand = substr($rg['token'], 0, 16);
139 139 $search = $rand . $ua_hash; $search = $rand . $ua_hash;
140 140 $params = array("sid" => $rg['sid'], "token" => $search); $params = array("sid" => $rg['sid'], "token" => $search);
141 $sql = "SELECT 1 AS junk FROM tokens"
141 $sql = "UPDATE tokens SET used = 1"
142 142 . " WHERE token = @@token@@" . " WHERE token = @@token@@"
143 . " AND sid = @@sid@@";
143 . " AND sid = @@sid@@"
144 . " AND used = 0";
144 145 $res = rg_sql_query_params($db, $sql, $params); $res = rg_sql_query_params($db, $sql, $params);
145 146 if ($res === FALSE) { if ($res === FALSE) {
146 147 rg_token_set_error("cannot get token (" . rg_sql_error() . ")"); rg_token_set_error("cannot get token (" . rg_sql_error() . ")");
147 148 break; break;
148 149 } }
149 150
150 $rows = rg_sql_num_rows($res);
151 $rows = rg_sql_affected_rows($res);
151 152 rg_sql_free_result($res); rg_sql_free_result($res);
152 153 if ($rows == 0) if ($rows == 0)
153 154 break; break;
 
... ... function rg_token_insert($db, $sid, $token)
199 200
200 201 /* /*
201 202 * Returns a token to be used on a form/url * Returns a token to be used on a form/url
202 * We generate only one per session.
203 * We generate only one per form, but multiple per session.
203 204 */ */
204 205 $rg_token = FALSE; $rg_token = FALSE;
205 206 function rg_token_get($db, $rg) function rg_token_get($db, $rg)
File tests/token.php changed (mode: 100644) (index f384d12..2fac7ce)
... ... rg_log_set_file("token.log");
14 14 $rg_no_db = TRUE; $rg_no_db = TRUE;
15 15 require_once("common.php"); require_once("common.php");
16 16
17 $sid = "session1";
18 $token = rg_token_get($db, $sid, "user-agent1");
17 $a = array("ua" => "user-agent1", "sid" => "session1");
18 $token = rg_token_get($db, $a);
19 19 if ($token === FALSE) { if ($token === FALSE) {
20 20 rg_log("Generating a token should not fail (" . rg_token_error() . ")!"); rg_log("Generating a token should not fail (" . rg_token_error() . ")!");
21 21 exit(1); exit(1);
22 22 } }
23 23 rg_log("Correct token: $token"); rg_log("Correct token: $token");
24 24
25 $a = array("sid" => $sid, "token" => $token);
25 $a['token'] = $token;
26 26 $r = rg_token_valid($db, $a); $r = rg_token_valid($db, $a);
27 27 if ($r === FALSE) { if ($r === FALSE) {
28 28 rg_log("Validating a correct token must work (" . rg_token_error() . ")!"); rg_log("Validating a correct token must work (" . rg_token_error() . ")!");
29 29 exit(1); exit(1);
30 30 } }
31 31
32 $r = rg_token_delete($db, $sid, $token);
32 $r = rg_token_delete($db, $a['sid'], $a['token']);
33 33 if ($r['ok'] != 1) { if ($r['ok'] != 1) {
34 34 rg_log("We should be able to delete a token!"); rg_log("We should be able to delete a token!");
35 35 exit(1); exit(1);
36 36 } }
37 37
38 $a = array("sid" => $sid, "token" => $token);
39 38 $r = rg_token_valid($db, $a); $r = rg_token_valid($db, $a);
40 39 if ($r !== FALSE) { if ($r !== FALSE) {
41 40 rg_log("Token should not be available after delete!"); rg_log("Token should not be available after delete!");
 
... ... if ($r !== FALSE) {
45 44
46 45 rg_log("Now, test pre-login sessions..."); rg_log("Now, test pre-login sessions...");
47 46 $rg_token = FALSE; /* we must remove it from memory */ $rg_token = FALSE; /* we must remove it from memory */
48 $sid = "Xsession2";
49 $token = rg_token_get($db, $sid, "user-agent1");
47 $a = array("ua" => "user-agent1", "sid" => "Xsession2");
48 $token = rg_token_get($db, $a);
50 49 if ($token === FALSE) { if ($token === FALSE) {
51 50 rg_log("Generating a token should not fail (" . rg_token_error() . ")!"); rg_log("Generating a token should not fail (" . rg_token_error() . ")!");
52 51 exit(1); exit(1);
53 52 } }
54 53 rg_log("Correct token: $token"); rg_log("Correct token: $token");
54 $a['token'] = $token;
55 55
56 $copy = "y" . substr($token, 1);
57 $a = array("sid" => $sid, "token" => $token);
58 $r = rg_token_valid($db, $a);
56 $copy = $a;
57 $copy['token'] = "y" . substr($a['token'], 1);
58 $r = rg_token_valid($db, $copy);
59 59 if ($r !== FALSE) { if ($r !== FALSE) {
60 60 rg_log("An altered token must return error!"); rg_log("An altered token must return error!");
61 61 exit(1); exit(1);
62 62 } }
63 63
64 $a = array("sid" => $sid, "token" => $token);
65 64 $r = rg_token_valid($db, $a); $r = rg_token_valid($db, $a);
66 65 if ($r === FALSE) { if ($r === FALSE) {
67 66 rg_log("Validating a correct token must work (" . rg_token_error() . ")!"); rg_log("Validating a correct token must work (" . rg_token_error() . ")!");
68 67 exit(1); exit(1);
69 68 } }
70 69
71 echo "token: OK!\n";
70
71 rg_log("Testing double posting...");
72 $rg_token = FALSE; /* we must remove it from memory */
73 $a = array("ua" => "user-agent3",
74 "sid" => "session_double");
75 $token = rg_token_get($db, $a);
76 if ($token === FALSE) {
77 rg_log("Generating a token should not fail (" . rg_token_error() . ")!");
78 exit(1);
79 }
80 $a['token'] = $token;
81
82 $r = rg_token_valid($db, $a);
83 if ($r === FALSE) {
84 rg_log("Calling 'valid' first time must work!");
85 exit(1);
86 }
87 $r = rg_token_valid($db, $a);
88 if ($r !== FALSE) {
89 rg_log("Calling 'valid' second time must NOT work!");
90 exit(1);
91 }
92
93 rg_log("OK!");
72 94 ?> ?>
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/rocketgit

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main