xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
Commit a87a60265dd93710118fc92b13121b7d7296823b

Checkpoint
Author: Catalin(ux) M. BOIE
Author date (UTC): 2014-12-16 21:19
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2014-12-16 21:19
Parent(s): c99a539501f24a82fb890a7ef59e2d97517246c5
Signing key:
Tree: 713907f6f8a37f283817c6a74f512b24cb2c3b26
File Lines added Lines deleted
Compare.txt 17 16
TODO 21 5
inc/bug.inc.php 2 2
inc/events.inc.php 27 35
inc/feedback/suggestion.php 7 2
inc/login/login.php 2 2
inc/plan.inc.php 5 5
inc/repo.inc.php 9 9
inc/struct.inc.php 8 0
inc/token.inc.php 28 20
inc/user.inc.php 5 8
inc/user/keys/keys.php 4 4
inc/user/pass/pass.php 2 2
inc/user/repo-page.php 1 0
inc/user/repo/bug/main.php 3 3
inc/user/repo/bug/show/add_note.php 2 2
inc/user/repo/bug/show/show.php 3 3
inc/util.inc.php 3 2
root/themes/default/hints/repo/edit_repo_path_rights.html 4 5
root/themes/default/hints/repo/edit_repo_refs_rights.html 16 6
root/themes/default/hints/repo/edit_repo_rights.html 1 1
root/themes/default/hints/repo/edit_rights.html 1 1
root/themes/default/repo/main.html 5 5
tests/Makefile 7 1
tests/http.inc.php 30 2
tests/http_create_account.php 36 6
tests/http_csrf.php 91 0
tests/token.php 10 6
File Compare.txt changed (mode: 100644) (index 920b851..829015f)
1 RocketGit Gitlab GitHub Gitorious unfuddle.com gitolite
1 RocketGit Gitlab GitHub Gitorious unfuddle.com gitolite
2 2
3 License GPLv3 ? Proprietary ? ? ?
3 License GPLv3 ? Proprietary ?open ? ?
4 4
5 5 [Features] [Features]
6 Easy instalation Yes No Yes No! ? Yes
7 SELinux friendly Yes ? ? ? ? ?
8 Distro friendly Yes No No No ? Yes
9 Bug tracker Yes Yes Yes No ? No
10 CLI commands (SSH) Yes ? ? ? ? ?
11 API ? ? Yes ? ? ?
12 Anonymous push Yes ? ? ? ? ?
13 Languages 1 ? ? ? ? ?
14 IPv6 Yes ? ? ? ? ?
6 Easy instalation Yes No Yes? No! ? Yes
7 SELinux friendly Yes ? ? ? ? ?
8 Distro friendly Yes No No No ? Yes
9 Bug tracker Yes Yes Yes No ? No
10 CLI commands (SSH) Yes ? ? ? ? ?
11 API HTTP(S) ? Yes ? ? ?
12 Anonymous push Yes ? No ? ? ?
13 Languages 1 ? ? ? ? ?
14 IPv6 Yes ? ? ? ? ?
15 Submodules ? ? ? ? ? ?
15 16
16 17
17 18 [Rights] [Rights]
18 Path control Yes ? ? ? ? ?
19 Refs control Yes ? ? ? ? ?
20 IP control Yes ? ? ? ? ?
19 Path control Yes ? ? ? ? ?
20 Refs control Yes ? ? ? ? ?
21 IP control Yes ? ? ? ? ?
21 22
22 23
23 24 [Details] [Details]
24 Language PHP Ruby+Perl Ruby Ruby ? Perl
25 Cache custom Redis ? ? ? No
25 Language PHP Ruby+Perl Ruby Ruby ? Perl
26 Cache custom Redis ? ? ? No
File TODO changed (mode: 100644) (index 712afb2..59dfe3d)
1 == Important: python moves to github ==
2 Nick Coghlan <ncoghlan-AT-gmail.com> is taking care of this, I should write an
3 e-mail to him. Or I may comment on LWN or "PEP 474".
4
1 5 == Where I stopped last time == == Where I stopped last time ==
2 [ ] Creating an account is not working. We test for 'E' right and is not
3 present. We should not check for 'E' if uid is 0?
4 [ ] Decide what rights to inject for 'refs'.
5 6 [ ] Friends will need a way to register an account with a full account type. [ ] Friends will need a way to register an account with a full account type.
6 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 Probably I will allow only one plan (Friends) till they all create
9 accounts. After this, I will remove this plan?
10 [ ]
7 11
8 12 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
13 [ ] Ce se intimpla daca un atacator seteaza un cookie pe .com, de exemplu.
14 El se va trimite si pe rocketgit.com. Deci, daca user-ul viziteaza site-ul
15 atacatorului, se seteaza acest cookie, care apoi va fi trimis catre rg.com.
16 astfel, poate controla cookie-ul (sid-ul), deci si token-ul. Cred ca e grav.
17 Cred ca asta face browser-ul. As putea sa schimb numele cookie-ului, si sa-l
18 semnez cumva: ma duc pe attack.com si acolo imi pune un cookie pe .com a=b.
19 Apoi, viziteaza good.com, si catre acesta trimite cookie-ul a=b.
20 Daca as lega good.com de a/b, as putea elimina cookie-urile rele.
21 [ ] "repo_submenu" seems to not be used, remove references.
22 [ ] http://nedbatchelder.com/blog/201405/github_monoculture.html
23 [ ] mchapman (subscriber, #66589) (http://lwn.net/Articles/623905/)
24 With a GitHub pull-request-based workflow I need a GitHub account (I've been resisting getting one for myself), I need to make sure I explicitly "fork" the repository within GitHub (simply pushing my copy of the repo to my account won't make pull requests work, as far as I know, because GitHub doesn't know that the original project and my project are "linked"), and I need to use the GitHub web interface to actually generate the pull request and take part in its review. If all of this isn't vendor lock-in, I don't know what is.
25 I've got bigger problems with the GitHub pull request workflow anyway. If you generate a pull request, discover that changes need to be made, you have two choices: you can create a new pull request, losing all comments from the previous one, or you have to add new commits. If you drop the to-be-pulled branch from your repository and replace it with a different branch with the same name, the pull request loses all of its comments.
26 No, I find the bigger problems are with pull-request based workflow that GitHub uses -- specifically, how that workflow interacts with code review. If your branch is reviewed and it needs modifications, then these modifications *should* be made to the original commits (not just tacked on as extra commits), which necessarily means the branch will be rebased. GitHub's workflow breaks completely when you rebase branches.
9 27 [ ] Should we delete previous session when user calls login if the user is [ ] Should we delete previous session when user calls login if the user is
10 28 already logged-in? already logged-in?
11 29 [ ] Talk in instalation about a php compiler? [ ] Talk in instalation about a php compiler?
12 [ ] In rg_token_valid, check User-Agent? pass $rg to rg_token_get and rg_token_valid?
13 30 [ ] cache_set should wait for an answer? Should we send an answer? [ ] cache_set should wait for an answer? Should we send an answer?
14 [ ] Add a http test for referer violation.
15 31 [ ] security_violation_no_exit -> security_violation? To not spend resources? [ ] security_violation_no_exit -> security_violation? To not spend resources?
16 32 [ ] Ar trebui sa validez si referer-ul. Si sa loghez pagina de pe care s-a facut [ ] Ar trebui sa validez si referer-ul. Si sa loghez pagina de pe care s-a facut
17 33 request-ul. request-ul.
File inc/bug.inc.php changed (mode: 100644) (index f691c17..1430901)
... ... function rg_bug_edit_high_level($db, &$rg)
1258 1258 break; break;
1259 1259 } }
1260 1260
1261 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
1261 if (!rg_token_valid($db, $rg)) {
1262 1262 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1263 1263 break; break;
1264 1264 } }
 
... ... function rg_bug_edit_high_level($db, &$rg)
1283 1283
1284 1284 if ($show_form) { if ($show_form) {
1285 1285 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1286 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
1286 $rg['rg_form_token'] = rg_token_get($db, $rg);
1287 1287
1288 1288 $exclude = array(0); $exclude = array(0);
1289 1289 $rg['bug']['HTML:state_select'] = $rg['bug']['HTML:state_select'] =
File inc/events.inc.php changed (mode: 100644) (index 8e645a6..9b67e23)
... ... function rg_event_process_queue($db, &$notify_list)
228 228 . rg_array2string($notify_list)); . rg_array2string($notify_list));
229 229
230 230 $ret = FALSE; $ret = FALSE;
231 $do_rollback = 0;
232 231 while (1) { while (1) {
233 $r = rg_sql_begin($db);
234 if ($r !== TRUE) {
235 rg_event_set_error("Cannot begin transaction"
236 . " (" . rg_sql_error() . ")");
237 break;
238 }
239 $do_rollback = 1;
232 $now = time();
240 233
241 234 // We limit to be able to deal with high prio tasks // We limit to be able to deal with high prio tasks
242 235 $sql = "SELECT * FROM events" $sql = "SELECT * FROM events"
236 . " WHERE fail = 0 AND next_try < $now"
243 237 . " ORDER BY prio, id" . " ORDER BY prio, id"
244 238 . " FOR UPDATE" . " FOR UPDATE"
245 239 . " LIMIT 100"; . " LIMIT 100";
 
... ... function rg_event_process_queue($db, &$notify_list)
251 245 break; break;
252 246 } }
253 247
254 $all_good = TRUE;
255 248 while (($row = rg_sql_fetch_array($res))) { while (($row = rg_sql_fetch_array($res))) {
256 $ev = unserialize($row['data']);
257 if ($ev === FALSE) {
258 rg_internal_error("Cannot unserialize data");
259 break;
260 }
261 $ev['prio'] = $row['prio'];
262 $ev['itime'] = $row['itime'];
249 $params = array("id" => $row['id']);
263 250
264 $r = rg_event_process($db, $ev);
265 if ($r !== TRUE) {
266 $all_good = FALSE;
251 while (1) {
252 $ev = unserialize($row['data']);
253 if ($ev === FALSE) {
254 rg_internal_error("Cannot unserialize data");
255 $sql = "UPDATE events SET fail = 1 WHERE id = @@id@@";
256 break;
257 }
258
259 $ev['prio'] = $row['prio'];
260 $ev['itime'] = $row['itime'];
261
262 $r = rg_event_process($db, $ev);
263 if ($r !== TRUE) {
264 $sql = "UPDATE events"
265 . " SET tries = tries + 1"
266 . ", next_try = $now + tries * 600"
267 . " WHERE id = @@id@@";
268 break;
269 }
270
271 if (isset($ev['notification']))
272 rg_event_notify($notify_list, $ev['notification'], "");
273
274 $sql = "DELETE FROM events WHERE id = @@id@@";
267 275 break; break;
268 276 } }
269 277
270 if (isset($ev['notification']))
271 rg_event_notify($notify_list, $ev['notification'], "");
272
273 $params = array("id" => $row['id']);
274 $sql = "DELETE FROM events WHERE id = @@id@@";
275 278 $res2 = rg_sql_query_params($db, $sql, $params); $res2 = rg_sql_query_params($db, $sql, $params);
276 279 rg_sql_free_result($res2); rg_sql_free_result($res2);
277 280 } }
278 281 rg_sql_free_result($res); rg_sql_free_result($res);
279 282
280 if ($all_good !== TRUE)
281 break;
282
283 $r = rg_sql_commit($db);
284 if ($r !== TRUE)
285 break;
286
287 283 $ret = $no_of_events; $ret = $no_of_events;
288 $do_rollback = 0;
289 284 break; break;
290 285 } }
291 286
292 if ($do_rollback == 1)
293 rg_sql_rollback($db);
294
295 287 rg_log_exit(); rg_log_exit();
296 288 rg_prof_end("event_process_queue"); rg_prof_end("event_process_queue");
297 289 return $ret; return $ret;
File inc/feedback/suggestion.php changed (mode: 100644) (index ae653d1..93065d4)
... ... while (1) {
15 15
16 16 $suggestion = rg_var_str("suggestion"); $suggestion = rg_var_str("suggestion");
17 17
18 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
18 if (!rg_valid_referer()) {
19 $errmsg[] = "invalid referer; try again";
20 break;
21 }
22
23 if (!rg_token_valid($db, $rg)) {
19 24 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
20 25 break; break;
21 26 } }
 
... ... while (1) {
40 45 if ($show_form == 1) { if ($show_form == 1) {
41 46 $rg['suggestion'] = $suggestion; $rg['suggestion'] = $suggestion;
42 47 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
43 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
48 $rg['rg_form_token'] = rg_token_get($db, $rg);
44 49 $_suggestion .= rg_template("suggestion.html", $rg); $_suggestion .= rg_template("suggestion.html", $rg);
45 50 } }
46 51
File inc/login/login.php changed (mode: 100644) (index 4c76425..d9ddfa0)
... ... while ($rg['doit'] == 1) {
15 15 break; break;
16 16 } }
17 17
18 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
18 if (!rg_token_valid($db, $rg)) {
19 19 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
20 20 break; break;
21 21 } }
 
... ... $rg['pass'] = $pass;
37 37 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
38 38 $rg['forgot_send'] = rg_re_url("/op/forgot_send"); $rg['forgot_send'] = rg_re_url("/op/forgot_send");
39 39 $rg['create_account'] = rg_re_url("/op/create_account"); $rg['create_account'] = rg_re_url("/op/create_account");
40 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
40 $rg['rg_form_token'] = rg_token_get($db, $rg);
41 41 $_login .= rg_template("user/login.html", $rg); $_login .= rg_template("user/login.html", $rg);
42 42 ?> ?>
File inc/plan.inc.php changed (mode: 100644) (index 4067072..e606071)
... ... function rg_plan_list_high_level($db, $rg)
246 246 break; break;
247 247
248 248 if (!rg_valid_referer()) { if (!rg_valid_referer()) {
249 $errmsg[] = "invalid referer; try again";
249 $del_errmsg[] = "invalid referer; try again";
250 250 break; break;
251 251 } }
252 252
253 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
253 if (!rg_token_valid($db, $rg)) {
254 254 $del_errmsg[] = "Invalid token. Try again."; $del_errmsg[] = "Invalid token. Try again.";
255 255 break; break;
256 256 } }
 
... ... function rg_plan_list_high_level($db, $rg)
271 271 return rg_template("admin/plans/list_err.html", $rg); return rg_template("admin/plans/list_err.html", $rg);
272 272 } }
273 273
274 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
274 $rg['rg_form_token'] = rg_token_get($db, $rg);
275 275 $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg); $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg);
276 276 $ret .= rg_template_table("admin/plans/list", $list, $rg); $ret .= rg_template_table("admin/plans/list", $list, $rg);
277 277 return $ret; return $ret;
 
... ... function rg_plan_edit_high_level($db, &$rg)
334 334 break; break;
335 335 } }
336 336
337 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
337 if (!rg_token_valid($db, $rg)) {
338 338 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
339 339 break; break;
340 340 } }
 
... ... function rg_plan_edit_high_level($db, &$rg)
353 353 if ($load_form) { if ($load_form) {
354 354 $rg['pi'] = $pi; $rg['pi'] = $pi;
355 355 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
356 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
356 $rg['rg_form_token'] = rg_token_get($db, $rg);
357 357 $ret .= rg_template("admin/plans/add_edit.html", $rg); $ret .= rg_template("admin/plans/add_edit.html", $rg);
358 358 } }
359 359
File inc/repo.inc.php changed (mode: 100644) (index 0f1489e..d6920df)
... ... rg_rights_register("repo_refs", $rg_repo_refs_rights, "FMH",
48 48 "rg_repo_compare_refs", "rg_repo_rights_inject"); "rg_repo_compare_refs", "rg_repo_rights_inject");
49 49 rg_rights_register("repo_path", $rg_repo_path_rights, "P", rg_rights_register("repo_path", $rg_repo_path_rights, "P",
50 50 "rg_repo_compare_paths", "rg_repo_rights_inject"); "rg_repo_compare_paths", "rg_repo_rights_inject");
51 rg_rights_register("repo", $rg_repo_rights, "AB",
51 rg_rights_register("repo", $rg_repo_rights, "AaB",
52 52 FALSE, "rg_repo_rights_inject"); FALSE, "rg_repo_rights_inject");
53 53
54 54 /* /*
 
... ... function rg_repo_rights_inject($db, $obj_id, $type, $owner, $uid)
105 105 break; break;
106 106
107 107 if (strcmp($type, "repo") == 0) { if (strcmp($type, "repo") == 0) {
108 $a['rights'] = "AB"; // access repo + add bugs
108 $a['rights'] = "AaB"; // access repo + access bug tracker + add bugs
109 109 $ret[] = $a; $ret[] = $a;
110 110 } else if (strcmp($type, "repo_refs") == 0) { } else if (strcmp($type, "repo_refs") == 0) {
111 111 $a['rights'] = "F"; // Fetch $a['rights'] = "F"; // Fetch
 
... ... function rg_repo_admin_delete_rights($db, $rg, $obj_id, &$errmsg)
1177 1177 return; return;
1178 1178 } }
1179 1179
1180 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
1180 if (!rg_token_valid($db, $rg)) {
1181 1181 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1182 1182 return; return;
1183 1183 } }
 
... ... function rg_repo_admin_rights($db, $rg, $type)
1273 1273 break; break;
1274 1274 } }
1275 1275
1276 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
1276 if (!rg_token_valid($db, $rg)) {
1277 1277 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1278 1278 break; break;
1279 1279 } }
 
... ... function rg_repo_admin_rights($db, $rg, $type)
1316 1316 $rg = rg_array_merge($rg, "", $a); $rg = rg_array_merge($rg, "", $a);
1317 1317 } }
1318 1318
1319 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
1319 $rg['rg_form_token'] = rg_token_get($db, $rg);
1320 1320 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1321 1321 $rg['HTML:list_errmsg'] = rg_template_errmsg($list_errmsg); $rg['HTML:list_errmsg'] = rg_template_errmsg($list_errmsg);
1322 1322 $rg['HTML:rights_checkboxes'] = rg_rights_checkboxes($type, "rights", $rg['HTML:rights_checkboxes'] = rg_rights_checkboxes($type, "rights",
 
... ... function rg_repo_admin_delete($db, $rg)
1374 1374 break; break;
1375 1375 } }
1376 1376
1377 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
1377 if (!rg_token_valid($db, $rg)) {
1378 1378 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1379 1379 break; break;
1380 1380 } }
 
... ... function rg_repo_admin_delete($db, $rg)
1395 1395
1396 1396 if ($show_form == 1) { if ($show_form == 1) {
1397 1397 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1398 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
1398 $rg['rg_form_token'] = rg_token_get($db, $rg);
1399 1399 $ret .= rg_template("user/repo/delete/sure.html", $rg); $ret .= rg_template("user/repo/delete/sure.html", $rg);
1400 1400 } }
1401 1401
 
... ... function rg_repo_edit_high_level($db, &$rg)
1439 1439 break; break;
1440 1440 } }
1441 1441
1442 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
1442 if (!rg_token_valid($db, $rg)) {
1443 1443 // TODO: replace all of these with a template // TODO: replace all of these with a template
1444 1444 $errmsg[] = "invalid token; try again."; $errmsg[] = "invalid token; try again.";
1445 1445 break; break;
 
... ... function rg_repo_edit_high_level($db, &$rg)
1483 1483 } }
1484 1484
1485 1485 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1486 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
1486 $rg['rg_form_token'] = rg_token_get($db, $rg);
1487 1487 $hints = array(); $hints = array();
1488 1488 $hints[]['HTML:hint'] = rg_template("hints/repo/create_repo.html", $rg); $hints[]['HTML:hint'] = rg_template("hints/repo/create_repo.html", $rg);
1489 1489 $rg['HTML:repo_edit_hints'] = rg_template_table("hints/list", $hints, $rg); $rg['HTML:repo_edit_hints'] = rg_template_table("hints/list", $hints, $rg);
File inc/struct.inc.php changed (mode: 100644) (index bd9ae25..8332f23)
... ... $rg_sql_struct[29]['other'] = array(
394 394 "CREATE UNIQUE INDEX users_username ON users(username)" "CREATE UNIQUE INDEX users_username ON users(username)"
395 395 ); );
396 396
397 $rg_sql_struct[30] = array();
398 $rg_sql_struct[30]['tables'] = array();
399 $rg_sql_struct[30]['other'] = array(
400 "events.fail" => "ALTER TABLE events ADD fail SMALLINT NOT NULL DEFAULT 0",
401 "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"
403 );
404
397 405
398 406 // This must be the last line // This must be the last line
399 407 $rg_sql_schema_ver = count($rg_sql_struct); $rg_sql_schema_ver = count($rg_sql_struct);
File inc/token.inc.php changed (mode: 100644) (index 34c1069..1b8f04b)
... ... function rg_token_get_master($db)
93 93 /* /*
94 94 * Returns TRUE if the token is valid * Returns TRUE if the token is valid
95 95 */ */
96 function rg_token_valid($db, $sid, $token)
96 function rg_token_valid($db, $rg)
97 97 { {
98 98 rg_prof_start("token_valid"); rg_prof_start("token_valid");
99 rg_log_enter("token_valid: sid=$sid token=$token");
99 rg_log_enter("token_valid: sid=" . $rg['sid'] . " token=" . $rg['token']
100 . " ua=" . $rg['ua']);
100 101
101 102 $ret = FALSE; $ret = FALSE;
102 103 while (1) { while (1) {
103 if (strncmp($sid, "X", 1) == 0) {
104 // We have a pre-login session.
105 // This means that token contains a random value
106 // plus a signature baeed on sid
104 $ua_hash = substr(sha1($rg['ua']), 0, 8);
107 105
108 if (strlen($token) != 32) {
109 rg_token_set_error("length of the token is invalid");
106 if (strncmp($rg['sid'], "X", 1) == 0) {
107 // We have a pre-login session.
108 if (strlen($rg['token']) != 32) {
109 rg_token_set_error("invalid token");
110 110 break; break;
111 111 } }
112 112
 
... ... function rg_token_valid($db, $sid, $token)
114 114 if ($key === FALSE) if ($key === FALSE)
115 115 break; break;
116 116
117 $rand = substr($token, 0, 16);
118 $sign = substr($token, 16);
117 $rand = substr($rg['token'], 0, 16);
118 $sign = substr($rg['token'], 16, 16);
119 119
120 $hash = hash_hmac("sha1", $rand . "-" . $sid, $key);
120 $data = $rand . $rg['sid'] . $ua_hash;
121 $hash = hash_hmac("sha1", $data, $key);
121 122 if ($hash === FALSE) { if ($hash === FALSE) {
122 123 rg_token_set_error("cannot compute hmac"); rg_token_set_error("cannot compute hmac");
123 124 break; break;
 
... ... function rg_token_valid($db, $sid, $token)
125 126
126 127 $hash = substr($hash, 0, 16); $hash = substr($hash, 0, 16);
127 128 if (strcmp($sign, $hash) != 0) { if (strcmp($sign, $hash) != 0) {
129 rg_log("DEBUG: sign=$sign != hash=$hash data=$data");
128 130 rg_token_set_error("token invalid"); rg_token_set_error("token invalid");
129 131 break; break;
130 132 } }
 
... ... function rg_token_valid($db, $sid, $token)
133 135 break; break;
134 136 } }
135 137
136 $params = array("sid" => $sid, "token" => $token);
138 $rand = substr($rg['token'], 0, 16);
139 $search = $rand . $ua_hash;
140 $params = array("sid" => $rg['sid'], "token" => $search);
137 141 $sql = "SELECT 1 AS junk FROM tokens" $sql = "SELECT 1 AS junk FROM tokens"
138 142 . " WHERE token = @@token@@" . " WHERE token = @@token@@"
139 143 . " AND sid = @@sid@@"; . " AND sid = @@sid@@";
 
... ... function rg_token_insert($db, $sid, $token)
198 202 * We generate only one per session. * We generate only one per session.
199 203 */ */
200 204 $rg_token = FALSE; $rg_token = FALSE;
201 function rg_token_get($db, $sid)
205 function rg_token_get($db, $rg)
202 206 { {
203 207 global $rg_token; global $rg_token;
204 208
205 rg_log_enter("token_get: sid=$sid");
209 rg_log_enter("token_get: sid=" . $rg['sid']);
206 210
207 211 $ret = FALSE; $ret = FALSE;
208 212 while (1) { while (1) {
209 if (empty($sid))
213 if (empty($rg['sid']))
210 214 break; break;
211 215
212 216 if ($rg_token !== FALSE) { if ($rg_token !== FALSE) {
 
... ... function rg_token_get($db, $sid)
214 218 break; break;
215 219 } }
216 220
217 $token = rg_id(16);
221 $rand = rg_id(16);
222 $ua_hash = substr(sha1($rg['ua']), 0, 8);
218 223
219 if (strncmp($sid, "X", 1) == 0) {
224 if (strncmp($rg['sid'], "X", 1) == 0) {
220 225 // we have a pre-login session // we have a pre-login session
221 226 $key = rg_token_get_master($db); $key = rg_token_get_master($db);
222 227 if ($key === FALSE) if ($key === FALSE)
223 228 break; break;
224 229
225 $data = $token . '-' . $sid;
230 $data = $rand . $rg['sid'] . $ua_hash;
226 231 $sign = hash_hmac("sha1", $data, $key); $sign = hash_hmac("sha1", $data, $key);
227 232 if ($sign === FALSE) { if ($sign === FALSE) {
228 233 rg_token_set_error("cannot compute hmac"); rg_token_set_error("cannot compute hmac");
229 234 break; break;
230 235 } }
231 236 $sign = substr($sign, 0, 16); $sign = substr($sign, 0, 16);
232 $token .= $sign;
237 $token = $rand . $sign;
238
239 rg_log("DEBUG: sign=$sign rand=$rand sid=" . $rg['sid'] . " ua_hash=$ua_hash");
233 240 } else { } else {
234 $r = rg_token_insert($db, $sid, $token);
241 $token = $rand . $ua_hash;
242 $r = rg_token_insert($db, $rg['sid'], $token);
235 243 if ($r['ok'] != 1) if ($r['ok'] != 1)
236 244 break; break;
237 245 } }
File inc/user.inc.php changed (mode: 100644) (index 2652c1e..04dd2ac)
... ... function rg_user_event_notify_user($db, $event)
71 71
72 72 if (strcmp($event['op'], "rename") == 0) { if (strcmp($event['op'], "rename") == 0) {
73 73 $r = rg_mail("mail/user/rename", $event); $r = rg_mail("mail/user/rename", $event);
74 if ($r === FALSE)
75 return FALSE;
74 } else {
75 $r = rg_mail("mail/user/welcome", $event);
76 76 } }
77
78 $r = rg_mail("mail/user/welcome", $event);
79 if ($r === FALSE)
80 return FALSE;
77 // TODO: we may want to return here an error?
81 78
82 79 return array(); return array();
83 80 } }
 
... ... function rg_user_edit_high_level($db, &$rg)
1430 1427 break; break;
1431 1428 } }
1432 1429
1433 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
1430 if (!rg_token_valid($db, $rg)) {
1434 1431 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1435 1432 break; break;
1436 1433 } }
 
... ... function rg_user_edit_high_level($db, &$rg)
1496 1493 $rg['HTML:checkbox_rights'] = rg_rights_checkboxes("user", $rg['HTML:checkbox_rights'] = rg_rights_checkboxes("user",
1497 1494 "rights", $ui['rights']); "rights", $ui['rights']);
1498 1495 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1499 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
1496 $rg['rg_form_token'] = rg_token_get($db, $rg);
1500 1497 $ret .= rg_template("user/add_edit.html", $rg); $ret .= rg_template("user/add_edit.html", $rg);
1501 1498 } }
1502 1499
File inc/user/keys/keys.php changed (mode: 100644) (index b9376c7..42228f8)
... ... if (rg_var_uint("add") == 1) {
24 24 break; break;
25 25 } }
26 26
27 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
27 if (!rg_token_valid($db, $rg)) {
28 28 $add_errmsg[] = "Invalid token. Try again."; $add_errmsg[] = "Invalid token. Try again.";
29 29 break; break;
30 30 } }
 
... ... if (rg_var_uint("add") == 1) {
37 37 } else if (rg_var_uint("delete") == 1) { } else if (rg_var_uint("delete") == 1) {
38 38 while (1) { while (1) {
39 39 if (!rg_valid_referer()) { if (!rg_valid_referer()) {
40 $errmsg[] = "invalid referer; try again";
40 $del_errmsg[] = "invalid referer; try again";
41 41 break; break;
42 42 } }
43 43
44 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
44 if (!rg_token_valid($db, $rg)) {
45 45 $del_errmsg[] = "Invalid token. Try again."; $del_errmsg[] = "Invalid token. Try again.";
46 46 break; break;
47 47 } }
 
... ... if ($rg_ssh_port != 0)
77 77 $hints[]['HTML:hint'] = rg_template("hints/ssh/key.html", $rg); $hints[]['HTML:hint'] = rg_template("hints/ssh/key.html", $rg);
78 78 $rg['HTML:hints'] = rg_template_table("hints/list", $hints, $rg); $rg['HTML:hints'] = rg_template_table("hints/list", $hints, $rg);
79 79
80 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
80 $rg['rg_form_token'] = rg_token_get($db, $rg);
81 81 $rg['key'] = $key; $rg['key'] = $key;
82 82
83 83 $_keys = rg_template("user/keys/main.html", $rg); $_keys = rg_template("user/keys/main.html", $rg);
File inc/user/pass/pass.php changed (mode: 100644) (index 68a2690..c6e503f)
... ... while (1) {
19 19 break; break;
20 20 } }
21 21
22 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
22 if (!rg_token_valid($db, $rg)) {
23 23 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
24 24 break; break;
25 25 } }
 
... ... while (1) {
46 46
47 47 if ($show_form == 1) { if ($show_form == 1) {
48 48 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
49 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
49 $rg['rg_form_token'] = rg_token_get($db, $rg);
50 50 $rg['old_pass'] = $old_pass; $rg['old_pass'] = $old_pass;
51 51 $rg['pass1'] = $pass1; $rg['pass1'] = $pass1;
52 52 $rg['pass2'] = $pass2; $rg['pass2'] = $pass2;
File inc/user/repo-page.php changed (mode: 100644) (index da95869..4c5b062)
... ... if (strcmp($_subop, "history") == 0) {
256 256 } }
257 257 } }
258 258
259 $rg['per_repo_menu'][$_subop] = 1;
259 260 $rg['HTML:repo_body'] = $_repo_body; $rg['HTML:repo_body'] = $_repo_body;
260 261 $rg['HTML:repo_right'] = $_repo_right; $rg['HTML:repo_right'] = $_repo_right;
261 262 $_repo_page = rg_template("repo/main.html", $rg); $_repo_page = rg_template("repo/main.html", $rg);
File inc/user/repo/bug/main.php changed (mode: 100644) (index 3d2f189..f5aa171)
... ... case 'list':
27 27 break; break;
28 28 } }
29 29
30 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
30 if (!rg_token_valid($db, $rg)) {
31 31 $_bug_body .= rg_warning("Error: invalid token; try again."); // TODO $_bug_body .= rg_warning("Error: invalid token; try again."); // TODO
32 exit(1);
32 break;
33 33 } }
34 34
35 35 $_search_name = rg_var_str("name"); $_search_name = rg_var_str("name");
 
... ... case 'list':
68 68 // Show remove for custom search // Show remove for custom search
69 69 // TODO: don't we check for uid also? Security problems? // TODO: don't we check for uid also? Security problems?
70 70 if (isset($filter['standard']) && ($filter['standard'] == 0)) { if (isset($filter['standard']) && ($filter['standard'] == 0)) {
71 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
71 $rg['rg_form_token'] = rg_token_get($db, $rg);
72 72 $rg['search_remove_errmsg'] = ""; $rg['search_remove_errmsg'] = "";
73 73 $_bug_body .= rg_template("repo/bug/search/remove.html", $rg); $_bug_body .= rg_template("repo/bug/search/remove.html", $rg);
74 74 } }
File inc/user/repo/bug/show/add_note.php changed (mode: 100644) (index eac3f61..13a565f)
... ... while (1) {
18 18 break; break;
19 19 } }
20 20
21 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
21 if (!rg_token_valid($db, $rg)) {
22 22 $note_errmsg[] = "Invalid token. Try again."; $note_errmsg[] = "Invalid token. Try again.";
23 23 break; break;
24 24 } }
 
... ... while (1) {
45 45
46 46 // add note form // add note form
47 47 $rg['HTML:note_errmsg'] = rg_template_errmsg($note_errmsg); $rg['HTML:note_errmsg'] = rg_template_errmsg($note_errmsg);
48 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
48 $rg['rg_form_token'] = rg_token_get($db, $rg);
49 49 $rg['note'] = $note; $rg['note'] = $note;
50 50 $rg['HTML:note_add'] = rg_template("repo/bug/note_add.html", $rg); $rg['HTML:note_add'] = rg_template("repo/bug/note_add.html", $rg);
51 51 ?> ?>
File inc/user/repo/bug/show/show.php changed (mode: 100644) (index b0d6e7c..5e7b1e7)
... ... while (1) {
68 68 break; break;
69 69 } }
70 70
71 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
71 if (!rg_token_valid($db, $rg)) {
72 72 $close_reopen_error = "Invalid token. Try again."; $close_reopen_error = "Invalid token. Try again.";
73 73 break; break;
74 74 } }
 
... ... while (1) {
157 157 break; break;
158 158 } }
159 159
160 if (!rg_token_valid($db, $rg['sid'], $rg['token'])) {
160 if (!rg_token_valid($db, $rg)) {
161 161 $delete_error = "Invalid token; try again."; $delete_error = "Invalid token; try again.";
162 162 break; break;
163 163 } }
 
... ... if ($ibug === FALSE)
179 179 rg_fatal("Cannot lookup bug!"); rg_fatal("Cannot lookup bug!");
180 180 $rg = rg_array_merge($rg, "bug", $ibug); $rg = rg_array_merge($rg, "bug", $ibug);
181 181
182 $rg['rg_form_token'] = rg_token_get($db, $rg['sid']);
182 $rg['rg_form_token'] = rg_token_get($db, $rg);
183 183 $_bug_show .= rg_template("repo/bug/show.html", $rg); $_bug_show .= rg_template("repo/bug/show.html", $rg);
184 184 ?> ?>
File inc/util.inc.php changed (mode: 100644) (index e362d7b..595382f)
... ... function rg_socket($path, $buf, $timeout, $tries)
1357 1357 } }
1358 1358
1359 1359 /* /*
1360 * Check if referer mathces current website
1360 * Check if referer matchces current website
1361 1361 */ */
1362 1362 function rg_valid_referer() function rg_valid_referer()
1363 1363 { {
 
... ... function rg_valid_referer()
1375 1375 if (strcasecmp($we, $ref) == 0) if (strcasecmp($we, $ref) == 0)
1376 1376 return TRUE; return TRUE;
1377 1377
1378 rg_security_violation_no_exit("invalid referer for form submission [$ref0]");
1378 rg_security_violation_no_exit("invalid referer for form submission"
1379 . " we=[$we] ref=[$ref] ref0=[$ref0]");
1379 1380 return FALSE; return FALSE;
1380 1381 } }
1381 1382
File root/themes/default/hints/repo/edit_repo_path_rights.html changed (mode: 100644) (index 8dbe040..fc5ad3c)
1 Example rights for references:<br />
2 <pre>
3 doc/.*\.jpg None = User cannot push jpeg files<br />
4 /user/{USER} Push = The pushing user (USER) is allowed to push files only in his folder inside /user/<br />
5 </pre>
1 Example rights for paths:<br />
2 User=[*] Path=[.*\.iso] Rights=[] - means that no user is allowed to push .iso files<br />
3 User=[friend] Path=[^doc/.*] Rights=[Push] - means that only user 'friend' is allowed to push commits that
4 alter some files/dirs in root doc folder.
File root/themes/default/hints/repo/edit_repo_refs_rights.html changed (mode: 100644) (index e673740..8327a8d)
1 1 Bad whitespace: if checked, commits with mixed tabs and spaces, trailing Bad whitespace: if checked, commits with mixed tabs and spaces, trailing
2 spaces/tabs etc. will be allowed.
3 <br /><br />
2 spaces/tabs etc. will be allowed.<br />
3 <br />
4
5 If your 'Reference' field does not start with '/', '/refs/heads/' will be
6 automatically prepended.<br />
7 <br />
4 8
5 9 Example rights for references:<br /> Example rights for references:<br />
6 <pre>
7 refs/heads/x Fetch + Push = Allow user to fetch/push in private namespace 'x'
8 refs/heads/{USER} Fetch + Push + Create branch + Delete branch = The push user 'USER' has rights to refs/heads/USER
9 </pre>
10 User=[friend] Reference=[refs/heads/x] Rights=[Fetch,Push] - means that user
11 friend is allowed to fetch and push into branch x.<br />
12 User=[user1] Reference=[release-.*] Rights=[Non fast-forward] - means that
13 user1 is allowed to force push (non fast-forward) in any branch
14 that starts with 'release-', for example 'release-1.0'.<br />
15 User=[*] Reference=[] Rights=[Anonymous push] Priority=[10] - means that any
16 user can anonymously push changes that will be automatically
17 transformed in a merge request. We recomend to activate it because
18 it will allow easy contributions to your project.
19
File root/themes/default/hints/repo/edit_repo_rights.html changed (mode: 100644) (index d79e11a..6fb684e)
1 TODO: Some hints here?
1 Here you can add rights for your co-workers.
File root/themes/default/hints/repo/edit_rights.html changed (mode: 100644) (index 2ac1fa0..1c8d9a9)
1 1 You do not have to grant yourself rights. You do not have to grant yourself rights.
2 You are the owner, so you have maximum rights.
2 You can observe the autogenerated rule that grants you maximum rights.
3 3 <br /><br /> <br /><br />
4 4
5 5 IP can be empty, meaning any IP will match. IP can be empty, meaning any IP will match.
File root/themes/default/repo/main.html changed (mode: 100644) (index d8dd3fa..e3b3bf1)
14 14
15 15 <div class="menu submenu"> <div class="menu submenu">
16 16 <ul> <ul>
17 <li><a href="@@url_repo@@/history">Last events</a></li>
18 <li><a href="@@url_repo@@/source">Source</a></li>
19 <li><a href="@@url_repo@@/mr">Merge requests</a></li>
20 <li><a href="@@url_repo@@/bug">Bugs</a></li>
21 @@if(@@can_admin@@ == 1){{<li><a href="@@url_repo@@/admin">Admin</a></li>}}{{}}
17 <li><a @@if(@@per_repo_menu.history@@ == 1){{class="selected"}}{{}} href="@@url_repo@@/history">Last events</a></li>
18 <li><a @@if(@@per_repo_menu.source@@ == 1){{class="selected"}}{{}} href="@@url_repo@@/source">Source</a></li>
19 <li><a @@if(@@per_repo_menu.mr@@ == 1){{class="selected"}}{{}} href="@@url_repo@@/mr">Merge requests</a></li>
20 <li><a @@if(@@per_repo_menu.bug@@ == 1){{class="selected"}}{{}} href="@@url_repo@@/bug">Bugs</a></li>
21 @@if(@@can_admin@@ == 1){{<li><a @@if(@@per_repo_menu.admin@@ == 1){{class="selected"}}{{}} href="@@url_repo@@/admin">Admin</a></li>}}{{}}
22 22 </ul> </ul>
23 23 </div> </div>
24 24 @@repo_submenu@@ @@repo_submenu@@
File tests/Makefile changed (mode: 100644) (index edf1cf0..9ed0791)
1 1 tests := token util log state cache prof db event rights keys user repo git bug \ tests := token util log state cache prof db event rights keys user repo git bug \
2 hook_update http_create_account http_settings
2 hook_update http_create_account http_login http_settings http_csrf
3 3 .PHONY: $(tests) .PHONY: $(tests)
4 4
5 5 all: $(tests) all: $(tests)
 
... ... hook_update:
52 52 http_create_account: http_create_account:
53 53 php http_create_account.php php http_create_account.php
54 54
55 http_login:
56 php http_login.php
57
55 58 http_settings: http_settings:
56 59 php http_settings.php php http_settings.php
57 60
61 http_csrf:
62 php http_csrf.php
63
58 64 .PHONY: clean .PHONY: clean
59 65 clean: clean:
60 66 @rm -f *.log *.strace *.strace.* *.out *.lock err-* @rm -f *.log *.strace *.strace.* *.out *.lock err-*
File tests/http.inc.php changed (mode: 100644) (index a800d2e..42b1887)
1 1 <?php <?php
2 2
3 if (!isset($test_ua))
4 $test_ua = "curl";
5
3 6 /* /*
4 7 * Data is an array * Data is an array
5 8 */ */
6 9 function do_req($url, $data, $headers) function do_req($url, $data, $headers)
7 10 { {
11 global $test_ua, $test_referer;
12
8 13 //rg_log_ml("do_req url[$url] data=" . print_r($data, TRUE) //rg_log_ml("do_req url[$url] data=" . print_r($data, TRUE)
9 14 // . "headers=" . print_r($headers, TRUE)); // . "headers=" . print_r($headers, TRUE));
10 15
 
... ... function do_req($url, $data, $headers)
17 22 } }
18 23 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
19 24 // We cannot use this because we will not have a // We cannot use this because we will not have a
20 // chanse to capture the sid.
25 // chance to capture the sid.
21 26 //curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1); //curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
22 27 curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_HEADER, 1);
23 28 curl_setopt($c, CURLOPT_HTTPHEADER, $headers); curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
24
29 curl_setopt($c, CURLOPT_USERAGENT, $test_ua);
30 curl_setopt($c, CURLOPT_REFERER, $test_referer);
25 31 $r = curl_exec($c); $r = curl_exec($c);
26 32 if ($r === FALSE) { if ($r === FALSE) {
27 33 rg_log("Cannot exec (url=$url), data: " . print_r($data, TRUE)); rg_log("Cannot exec (url=$url), data: " . print_r($data, TRUE));
 
... ... function do_req($url, $data, $headers)
76 82 */ */
77 83 function test_login($url, &$good_sid) function test_login($url, &$good_sid)
78 84 { {
85 global $test_ua;
86
79 87 // First we need to load the form so we can get the token // First we need to load the form so we can get the token
80 88 // We provide an old cookie to test if we generate a new pre-login one // We provide an old cookie to test if we generate a new pre-login one
81 89 $data = array(); $data = array();
 
... ... function test_restore($db)
141 149 rg_cache_unset("user::4"); rg_cache_unset("user::4");
142 150 } }
143 151
152 /*
153 * Set user agent
154 */
155 function test_set_ua($s)
156 {
157 global $test_ua;
158
159 $test_ua = $s;
160 }
161
162 /*
163 * Set referer
164 */
165 function test_set_referer($s)
166 {
167 global $test_referer;
168
169 $test_referer = $s;
170 }
171
144 172 ?> ?>
File tests/http_create_account.php changed (mode: 100644) (index 0579b85..8760e4c)
... ... require_once("http.inc.php");
10 10
11 11 rg_log_set_file("http_create_account.log"); rg_log_set_file("http_create_account.log");
12 12
13 $rg_sql = "host=localhost user=rocketgit dbname=rocketgit connect_timeout=10";
13 14 $rg_no_db = TRUE; $rg_no_db = TRUE;
14 15 require_once("common.php"); require_once("common.php");
15 16
 
... ... rg_log("Test create account");
18 19 $data = array(); $data = array();
19 20 $headers = array(); $headers = array();
20 21 $r = do_req($test_url . "/op/create_account", $data, $headers); $r = do_req($test_url . "/op/create_account", $data, $headers);
21 file_put_contents("http_create_account-load.log", print_r($r, TRUE));
22 22 if ($r === FALSE) { if ($r === FALSE) {
23 23 rg_log("Cannot load create_account page!"); rg_log("Cannot load create_account page!");
24 24 exit(1); exit(1);
 
... ... $good_token = $r['token'];
29 29 $uniq = time(); $uniq = time();
30 30
31 31 // Second, do the request // Second, do the request
32 $username = "http1-$uniq";
32 33 $data = array( $data = array(
33 34 "uid" => 0, "uid" => 0,
34 35 "doit" => 1, "doit" => 1,
35 36 "token" => $good_token, "token" => $good_token,
36 "username" => "http1-$uniq",
37 "realname" => "http1-$uniq's real name",
38 "email" => "a fake email $uniq",
37 "username" => $username,
38 "realname" => "http1-$uniq real name",
39 "email" => "http_create_account_$uniq@embedromix.ro",
39 40 "pass" => "cucurigu", "pass" => "cucurigu",
40 41 "pass2" => "cucurigu", "pass2" => "cucurigu",
41 42 "plan_id" => 9, "plan_id" => 9,
42 43 "session_time" => 60 "session_time" => 60
43 44 ); );
44 45 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
45 $r = do_req($test_url . "/op/create_account", $data, $headers);
46 file_put_contents("http_create_account-add.log", print_r($r, TRUE));
46 $r = do_req($test_url . "/op/create_account?t=create_account", $data, $headers);
47 47 if (!strstr($r['body'], "Your account was created")) { if (!strstr($r['body'], "Your account was created")) {
48 file_put_contents("http_create_account.log", print_r($r, TRUE));
48 49 rg_log("Cannot create account"); rg_log("Cannot create account");
49 50 exit(1); exit(1);
50 51 } }
51 52
53 $sql = "SELECT * FROM users WHERE username = '$username'";
54 $res = rg_sql_query($db, $sql);
55 if ($res === FALSE)
56 exit(1);
57 $rows = rg_sql_num_rows($res);
58 if ($rows === 0) {
59 rg_log("Seems the account is not created: rows == 0!");
60 exit(1);
61 }
62 $row = rg_sql_fetch_array($res);
63 rg_sql_free_result($res);
64
65 $data['pass'] = rg_user_pass($row['salt'], $data['pass']);
66 $data['is_admin'] = 0; // to be sure we do not create admin accounts
67 foreach ($data as $k => $v) {
68 if (!isset($row[$k]))
69 continue;
70
71 if (strcmp($k, "uid") == 0)
72 continue;
73 if (strcmp($k, "pass") == 0)
74 continue;
75
76 if (strcmp($row[$k], $v) != 0) {
77 rg_log("Key $k does not match: row=" . $row[$k] . " data=" . $data[$k]);
78 exit(1);
79 }
80 rg_log("Key $k matches.");
81 }
52 82
53 83 rg_log("Done!"); rg_log("Done!");
54 84 ?> ?>
File tests/http_csrf.php added (mode: 100644) (index 0000000..7ccd9b5)
1 <?php
2 error_reporting(E_ALL | E_STRICT);
3 ini_set("track_errors", "On");
4
5 $rg_cache_debug = TRUE;
6
7 $INC = dirname(__FILE__) . "/../inc";
8 require_once(dirname(__FILE__) . "/config.php");
9 require_once($INC . "/init.inc.php");
10 require_once($INC . "/util.inc.php");
11 require_once("http.inc.php");
12
13 rg_log_set_file("http_csrf.log");
14
15 $rg_sql = "host=localhost user=rocketgit dbname=rocketgit connect_timeout=10";
16 $rg_no_db = TRUE;
17 require_once("common.php");
18
19 $rg_cache_enable = TRUE;
20
21 $now = time();
22
23 $r = test_login($test_url, $good_sid);
24 if ($r === FALSE) {
25 rg_log("Cannot login!");
26 exit(1);
27 }
28
29 rg_log("Loading suggestion form (ua test)");
30 test_set_ua("user-agent-1");
31 test_set_referer($test_url);
32 $data = array();
33 $headers = array("Cookie: sid=" . $good_sid);
34 $r = do_req($test_url . "/op/suggestion?t=load_suggestion_form_ua", $data, $headers);
35 if (!stristr($r['body'], "action=\"/op/suggestion\"")) {
36 file_put_contents("http_csrf.log", $r);
37 rg_log_ml("Cannot load form!");
38 exit(1);
39 }
40 $good_token = $r['token'];
41
42 rg_log("Try posting with different user-agent: should not work");
43 test_set_ua("user-agent-2");
44 $data = array(
45 "doit" => 1,
46 "token" => $good_token,
47 "suggestion" => "bla bla bla"
48 );
49 $headers = array("Cookie: sid=" . $good_sid);
50 $r = do_req($test_url . "/op/suggestion?t=post_suggestion_form_diff_ua", $data, $headers);
51 if (!stristr($r['body'], "invalid token")) {
52 file_put_contents("http_csrf.log", $r['body']);
53 rg_log_ml("Seems I could add a suggestion bypassing CSRF"
54 . " protection based on user-agent!");
55 exit(1);
56 }
57
58
59 rg_log("Loading suggestion form (referer test)");
60 test_set_ua("user-agent-1");
61 test_set_referer($test_url);
62 $data = array();
63 $headers = array("Cookie: sid=" . $good_sid);
64 $r = do_req($test_url . "/op/suggestion?t=load_suggestion_form_referer", $data, $headers);
65 if (!stristr($r['body'], "action=\"/op/suggestion\"")) {
66 file_put_contents("http_csrf.log", $r);
67 rg_log_ml("Cannot load form!");
68 exit(1);
69 }
70 $good_token = $r['token'];
71
72 rg_log("Try posting with different referer: should not work");
73 test_set_ua("user-agent-1");
74 test_set_referer("http://attacker.com:4000/bla");
75 $data = array(
76 "doit" => 1,
77 "token" => $good_token,
78 "suggestion" => "bla bla bla"
79 );
80 $headers = array("Cookie: sid=" . $good_sid);
81 $r = do_req($test_url . "/op/suggestion?t=post_suggestion_form_diff_referer", $data, $headers);
82 if (!stristr($r['body'], "invalid referer")) {
83 file_put_contents("http_csrf.log", $r['body']);
84 rg_log_ml("Seems I could add a suggestion bypassing CSRF"
85 . " protection based on referer!");
86 exit(1);
87 }
88
89
90 rg_log("Done!");
91 ?>
File tests/token.php changed (mode: 100644) (index 7379a69..f384d12)
... ... $rg_no_db = TRUE;
15 15 require_once("common.php"); require_once("common.php");
16 16
17 17 $sid = "session1"; $sid = "session1";
18 $token = rg_token_get($db, $sid);
18 $token = rg_token_get($db, $sid, "user-agent1");
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 $r = rg_token_valid($db, $sid, $token);
25 $a = array("sid" => $sid, "token" => $token);
26 $r = rg_token_valid($db, $a);
26 27 if ($r === FALSE) { if ($r === FALSE) {
27 28 rg_log("Validating a correct token must work (" . rg_token_error() . ")!"); rg_log("Validating a correct token must work (" . rg_token_error() . ")!");
28 29 exit(1); exit(1);
 
... ... if ($r['ok'] != 1) {
34 35 exit(1); exit(1);
35 36 } }
36 37
37 $r = rg_token_valid($db, $sid, $token);
38 $a = array("sid" => $sid, "token" => $token);
39 $r = rg_token_valid($db, $a);
38 40 if ($r !== FALSE) { if ($r !== FALSE) {
39 41 rg_log("Token should not be available after delete!"); rg_log("Token should not be available after delete!");
40 42 exit(1); exit(1);
 
... ... if ($r !== FALSE) {
44 46 rg_log("Now, test pre-login sessions..."); rg_log("Now, test pre-login sessions...");
45 47 $rg_token = FALSE; /* we must remove it from memory */ $rg_token = FALSE; /* we must remove it from memory */
46 48 $sid = "Xsession2"; $sid = "Xsession2";
47 $token = rg_token_get($db, $sid);
49 $token = rg_token_get($db, $sid, "user-agent1");
48 50 if ($token === FALSE) { if ($token === FALSE) {
49 51 rg_log("Generating a token should not fail (" . rg_token_error() . ")!"); rg_log("Generating a token should not fail (" . rg_token_error() . ")!");
50 52 exit(1); exit(1);
 
... ... if ($token === FALSE) {
52 54 rg_log("Correct token: $token"); rg_log("Correct token: $token");
53 55
54 56 $copy = "y" . substr($token, 1); $copy = "y" . substr($token, 1);
55 $r = rg_token_valid($db, $sid, $copy);
57 $a = array("sid" => $sid, "token" => $token);
58 $r = rg_token_valid($db, $a);
56 59 if ($r !== FALSE) { if ($r !== FALSE) {
57 60 rg_log("An altered token must return error!"); rg_log("An altered token must return error!");
58 61 exit(1); exit(1);
59 62 } }
60 63
61 $r = rg_token_valid($db, $sid, $token);
64 $a = array("sid" => $sid, "token" => $token);
65 $r = rg_token_valid($db, $a);
62 66 if ($r === FALSE) { if ($r === FALSE) {
63 67 rg_log("Validating a correct token must work (" . rg_token_error() . ")!"); rg_log("Validating a correct token must work (" . rg_token_error() . ")!");
64 68 exit(1); exit(1);
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://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

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