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 c42469d7e9ea84b23776c945cb0dd46ea82a589f

Lots of fixes, mostly cache performance ones.
Author: Catalin(ux) M. BOIE
Author date (UTC): 2015-06-24 04:22
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2015-06-24 04:24
Parent(s): 7998f5b0ba9cbd06deb5a5e5270629f9213cf2b7
Signing key:
Tree: 978e2636d6836dcc33bab4ae85568378de55bfac
File Lines added Lines deleted
README 1 0
TODO 36 4
duilder.conf 1 1
inc/admin.inc.php 5 5
inc/bug.inc.php 14 11
inc/cache.inc.php 35 13
inc/dispatch/dispatch.php 1 1
inc/events.inc.php 5 1
inc/feedback/suggestion.php 2 2
inc/keys.inc.php 1 1
inc/log.inc.php 8 5
inc/login/login.php 2 2
inc/plan.inc.php 7 7
inc/repo.inc.php 32 21
inc/rights.inc.php 4 3
inc/sess.inc.php 5 5
inc/state.inc.php 2 2
inc/token.inc.php 76 45
inc/user.inc.php 18 15
inc/user/keys/keys.php 3 3
inc/user/pass/pass.php 2 2
inc/user/repo/bug/main.php 3 2
inc/user/repo/bug/show/add_note.php 3 2
inc/user/repo/bug/show/show.php 91 57
inc/util.inc.php 19 9
root/index.php 4 4
root/themes/default/download-vm.html 3 3
root/themes/default/features.html 2 2
root/themes/default/repo/bug/b_close.html 0 1
root/themes/default/repo/bug/b_del.html 6 0
root/themes/default/repo/bug/b_edit.html 0 1
root/themes/default/repo/bug/b_reopen.html 0 1
root/themes/default/repo/bug/b_unwatch.html 0 6
root/themes/default/repo/bug/b_watch.html 3 3
root/themes/default/repo/bug/show.html 1 7
scripts/cache.php 20 8
tests/Makefile 5 4
tests/git2.php 2 2
tests/helpers.inc.php 3 2
tests/http.inc.php 29 10
tests/http_admin.php 7 3
tests/http_bug.php 45 29
tests/http_create_account.php 1 1
tests/http_csrf.php 20 18
tests/http_login.php 2 2
tests/http_settings.php 9 19
tests/token.php 12 11
File README changed (mode: 100644) (index ceed2aa..93e08e7)
5 5 . License: GPLv3 . License: GPLv3
6 6 . Language: PHP (plans to rewrite in C in the near future) . Language: PHP (plans to rewrite in C in the near future)
7 7 . Database: PostgreSQL . Database: PostgreSQL
8 . Project start date: 2011-03-04
8 9
9 10
10 11 == Features == == Features ==
File TODO changed (mode: 100644) (index a520351..c713968)
1 1 == Where I stopped last time == == Where I stopped last time ==
2 [ ] Creating git folder is not always working?
3 De verificat toate pe rocketgit.com.
4 [ ] What if a user passed </textarea> or <xss> into a field for edit?!
5 We may have a xss attack! Bad! Bad!
2 [ ] admin_delete_rights::delete, was not protected against csrf/ua!
3 Other places? Use a unit test for this stuff?
4 [ ] Seems I do not insert a history item on repo creation!
5 [ ] Bugs caching page is not working anymore (after NO_WAIT changes)
6 Seems I regenerate the CSRF tokens!
7 [ ] tests are failing!
6 8 [ ] [ ]
7 9
10 == CSRF logic ==
11 - Generate a token for a specific form (call rg_token_get with an $op)
12 Why I do not use a key per user not a master key?! Maybe because I have
13 to store it in db. Why not? Because of caching of the pages...
14 - For a form, we create a token based on sess, ua, tag and a random string.
15 We store it in sess::SID::token::tag to be reused next time we
16 load that specific form.
17 Also, we store it in sess::SID::used_tokens::TOKEN=0 to optimize
18 for when we receive the POST request (to not lookup in db).
19 - When checking the validity, we look it up in sess::SID::used_tokens and
20 compare with 0. If true, we know that token is valid and not used.
21
22
8 23 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
24 [ ] Some rg_cache_unset may trigger an error. Case by case we have to
25 analyze the impact. We may want to give an error to the user.
26 I am thinking at tokens. Maybe we do ot want to mark it as used in
27 db if we cannot set it as used in the cache. Else, an attacker may
28 reuse the token.
29 [ ] Run the tests also with cache down (on the server side).
30 [ ] When showing empty rights, maybe replace with "DENY"?
31 [ ] Show who is watching a bug.
32 [ ] Mess with session_*() functions to achieve some vars persistence.
33 [ ] Add a para to rg_token_get to specify the form (ex: 'login'), this way
34 we can still cache the other pages, becasue that token is not
35 marked as used.
36 [ ] Add some area with citations?
37 - I find people who think open-source is anti-capitalism to be kind
38 of naive and slightly stupid. (bloomberg.com)
39 [ ] Build a big repo from all hosted projects!
40 [ ] Add a link to comments to be able to pass that link to others.
9 41 [ ] First page can be cached at least 10 minutes? I think not because of [ ] First page can be cached at least 10 minutes? I think not because of
10 42 logout token. What if the user is not logged in?! Yep, we can do it. logout token. What if the user is not logged in?! Yep, we can do it.
11 43 ETag! What about the cookies?! ETag! What about the cookies?!
File duilder.conf changed (mode: 100644) (index f032543..8d2fdc2)
1 1 PRJ="rocketgit" PRJ="rocketgit"
2 VER="0.34"
2 VER="0.35"
3 3 REV="1" REV="1"
4 4 EXCLUDE=".exclude" EXCLUDE=".exclude"
5 5 EXPORT_PATH="/data/www/umbrella/kernel/us/rocketgit" EXPORT_PATH="/data/www/umbrella/kernel/us/rocketgit"
File inc/admin.inc.php changed (mode: 100644) (index 8aa3f0b..8d34f3d)
... ... function rg_admin_invites_high_level($db, $rg)
120 120 break; break;
121 121 } }
122 122
123 if (!rg_token_valid($db, $rg, FALSE)) {
123 if (!rg_token_valid($db, $rg, 'admin_invites_hl', FALSE)) {
124 124 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
125 125 break; break;
126 126 } }
 
... ... function rg_admin_invites_high_level($db, $rg)
178 178 if ($show_form) { if ($show_form) {
179 179 $rg['inv'] = $inv; $rg['inv'] = $inv;
180 180 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
181 $rg['rg_form_token'] = rg_token_get($db, $rg);
181 $rg['rg_form_token'] = rg_token_get($db, $rg, 'admin_invites_hl');
182 182 $ret .= rg_template("admin/invites/invites.html", $rg, TRUE /* xss */); $ret .= rg_template("admin/invites/invites.html", $rg, TRUE /* xss */);
183 183 } }
184 184
 
... ... function rg_init($db, $rg)
231 231 break; break;
232 232 } }
233 233
234 if (!rg_token_valid($db, $rg, FALSE)) {
234 if (!rg_token_valid($db, $rg, 'init', FALSE)) {
235 235 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
236 236 break; break;
237 237 } }
 
... ... function rg_init($db, $rg)
251 251
252 252 if ($load_form) { if ($load_form) {
253 253 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
254 $rg['rg_form_token'] = rg_token_get($db, $rg);
254 $rg['rg_form_token'] = rg_token_get($db, $rg, 'init');
255 255 $ret .= rg_template("admin/init.html", $rg, TRUE /* xss */); $ret .= rg_template("admin/init.html", $rg, TRUE /* xss */);
256 256 } }
257 257
 
... ... function rg_clean_logs($dir)
413 413
414 414 $limit_ts = gmmktime(0, 0, 0, gmdate('m'), gmdate('d') - $rg_logs_lifetime); $limit_ts = gmmktime(0, 0, 0, gmdate('m'), gmdate('d') - $rg_logs_lifetime);
415 415 $limit = gmdate("Ymd", $limit_ts); $limit = gmdate("Ymd", $limit_ts);
416 rg_log("limit_ts=$limit_ts limit=$limit");
416 //rg_log("limit_ts=$limit_ts limit=$limit");
417 417
418 418 foreach ($files as $file) { foreach ($files as $file) {
419 419 $ymd = preg_replace('/.*-([0-9]*)\.log/', '$1', $file); $ymd = preg_replace('/.*-([0-9]*)\.log/', '$1', $file);
File inc/bug.inc.php changed (mode: 100644) (index 002e383..8273d34)
... ... function rg_bug_info($db, $repo_id, $bug_id)
378 378 rg_sql_free_result($res); rg_sql_free_result($res);
379 379
380 380 // We set the cache even on non-existent bug // We set the cache even on non-existent bug
381 rg_cache_set($key, $ret);
381 rg_cache_set($key, $ret, RG_SOCKET_NO_WAIT);
382 382 break; break;
383 383 } }
384 384
 
... ... function rg_bug_edit($db, $login_ui, $ri, $data)
484 484 rg_sql_free_result($res); rg_sql_free_result($res);
485 485
486 486 // Add reporter and assignee to the watch list // Add reporter and assignee to the watch list
487 $r = rg_watch_add($db, "bug", $login_ui['uid'], $ri['repo_id'],
488 $data['bug_id']);
489 if ($r === FALSE) {
490 rg_bug_set_error("cannot add to watch list"
491 . " (" . rg_watch_error() . ")");
492 break;
487 if ($add == 1) {
488 $r = rg_watch_add($db, 'bug', $login_ui['uid'],
489 $ri['repo_id'], $data['bug_id']);
490 if ($r === FALSE) {
491 rg_bug_set_error("cannot add to watch list"
492 . " (" . rg_watch_error() . ")");
493 break;
494 }
493 495 } }
494 496
495 497 if ($data['assigned_uid'] > 0) { if ($data['assigned_uid'] > 0) {
496 $r = rg_watch_add($db, "bug", $data['assigned_uid'],
498 $r = rg_watch_add($db, 'bug', $data['assigned_uid'],
497 499 $ri['repo_id'], $data['bug_id']); $ri['repo_id'], $data['bug_id']);
498 500 if ($r === FALSE) { if ($r === FALSE) {
499 501 rg_bug_set_error("cannot add to watch list" rg_bug_set_error("cannot add to watch list"
 
... ... function rg_bug_edit($db, $login_ui, $ri, $data)
533 535 $data['exists'] = 1; $data['exists'] = 1;
534 536 rg_bug_cosmetic($db, $data); rg_bug_cosmetic($db, $data);
535 537 $key = $ri['repo_id'] . "::bugs::" . $data['bug_id']; $key = $ri['repo_id'] . "::bugs::" . $data['bug_id'];
536 rg_cache_set($key, $data);
538 rg_cache_set($key, $data, RG_SOCKET_NO_WAIT);
537 539
538 540 rg_event_signal_daemon("", 0); rg_event_signal_daemon("", 0);
539 541
 
... ... function rg_bug_edit_high_level($db, &$rg)
1302 1304 break; break;
1303 1305 } }
1304 1306
1305 if (!rg_token_valid($db, $rg, FALSE)) {
1307 if (!rg_token_valid($db, $rg, 'bug_edit_hl', FALSE)) {
1306 1308 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1307 1309 break; break;
1308 1310 } }
 
... ... function rg_bug_edit_high_level($db, &$rg)
1325 1327
1326 1328 if ($show_form) { if ($show_form) {
1327 1329 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1328 $rg['rg_form_token'] = rg_token_get($db, $rg);
1330 $rg['rg_form_token'] = rg_token_get($db, $rg, 'bug_edit_hl');
1331 $rg['rg_form_token_tag'] = 'bug_edit_hl';
1329 1332
1330 1333 $exclude = array(0); $exclude = array(0);
1331 1334 $rg['bug']['HTML:state_select'] = $rg['bug']['HTML:state_select'] =
File inc/cache.inc.php changed (mode: 100644) (index 7ef4077..2fece33)
... ... function rg_cache_get($ns_var)
291 291
292 292 rg_prof_start("cache_get"); rg_prof_start("cache_get");
293 293 if ($rg_cache_debug) if ($rg_cache_debug)
294 rg_log_enter("cache_get($ns_var)");
294 rg_log_enter("cache_get: $ns_var");
295 295
296 296 $ret = FALSE; $ret = FALSE;
297 297 while (1) { while (1) {
298 298 $ret = rg_cache_core_get($ns_var); $ret = rg_cache_core_get($ns_var);
299 if ($ret !== FALSE)
299 if ($ret !== FALSE) {
300 if ($rg_cache_debug)
301 rg_log('Found in core. Good!');
300 302 break; break;
303 }
301 304
302 305 if ($rg_cache_enable === FALSE) if ($rg_cache_enable === FALSE)
303 306 break; break;
304 307
305 308 $c = rg_socket($rg_cache_socket, $c = rg_socket($rg_cache_socket,
306 "GET " . $ns_var . "\n", $rg_cache_timeout, 1);
309 "GET F= " . $ns_var . "\n", $rg_cache_timeout, 1, 0);
307 310 if ($c === FALSE) if ($c === FALSE)
308 311 break; break;
309 312
 
... ... function rg_cache_prepare($s)
346 349 /* /*
347 350 * Sets a variable in the cache daemon * Sets a variable in the cache daemon
348 351 */ */
349 function rg_cache_set($ns_var, $value)
352 function rg_cache_set($ns_var, $value, $flags)
350 353 { {
351 354 global $rg_cache_socket; global $rg_cache_socket;
352 355 global $rg_cache_timeout; global $rg_cache_timeout;
 
... ... function rg_cache_set($ns_var, $value)
355 358
356 359 rg_prof_start("cache_set"); rg_prof_start("cache_set");
357 360 if ($rg_cache_debug) if ($rg_cache_debug)
358 rg_log_ml_enter("cache_set: $ns_var = " . print_r($value, TRUE));
361 rg_log_ml_enter("cache_set: flags=$flags"
362 . " $ns_var = " . print_r($value, TRUE));
359 363
360 364 $ret = FALSE; $ret = FALSE;
361 365 while (1) { while (1) {
 
... ... function rg_cache_set($ns_var, $value)
364 368 if ($rg_cache_enable === FALSE) if ($rg_cache_enable === FALSE)
365 369 break; break;
366 370
367 $c = rg_socket($rg_cache_socket, "SET " . $ns_var . "="
368 . rg_cache_prepare($value) . "\n", $rg_cache_timeout, 3);
371 $f = '';
372 if ($flags & RG_SOCKET_NO_WAIT)
373 $f .= 'W';
374
375 $c = rg_socket($rg_cache_socket, "SET F=$f " . $ns_var . "="
376 . rg_cache_prepare($value) . "\n", $rg_cache_timeout, 3, $flags);
369 377 if ($c === FALSE) if ($c === FALSE)
370 378 break; break;
371 379
380 if ($flags & RG_SOCKET_NO_WAIT) {
381 $ret = TRUE;
382 break;
383 }
384
372 385 if (strncmp($c, "OK", 2) != 0) if (strncmp($c, "OK", 2) != 0)
373 386 break; break;
374 387
 
... ... function rg_cache_inc($ns_var)
404 417 break; break;
405 418
406 419 $c = rg_socket($rg_cache_socket, $c = rg_socket($rg_cache_socket,
407 "INC " . $ns_var . "\n", $rg_cache_timeout, 1);
420 "INC F= " . $ns_var . "\n", $rg_cache_timeout, 1, 0);
408 421 if ($c === FALSE) if ($c === FALSE)
409 422 break; break;
410 423
 
... ... function rg_cache_inc($ns_var)
428 441 /* /*
429 442 * Unsets a variable in the cache daemon * Unsets a variable in the cache daemon
430 443 */ */
431 function rg_cache_unset($ns_var)
444 function rg_cache_unset($ns_var, $flags)
432 445 { {
433 446 global $rg_cache_socket; global $rg_cache_socket;
434 447 global $rg_cache_timeout; global $rg_cache_timeout;
 
... ... function rg_cache_unset($ns_var)
437 450
438 451 rg_prof_start("cache_unset"); rg_prof_start("cache_unset");
439 452 if ($rg_cache_debug) if ($rg_cache_debug)
440 rg_log_enter("cache_unset($ns_var)"
453 rg_log_enter("cache_unset($ns_var) flags=$flags"
441 454 . " enable=" . ($rg_cache_enable ? "true" : "false")); . " enable=" . ($rg_cache_enable ? "true" : "false"));
442 455
443 456 $ret = FALSE; $ret = FALSE;
 
... ... function rg_cache_unset($ns_var)
447 460 if ($rg_cache_enable === FALSE) if ($rg_cache_enable === FALSE)
448 461 break; break;
449 462
463 $f = '';
464 if ($flags & RG_SOCKET_NO_WAIT)
465 $f .= 'W';
466
450 467 $ret = rg_socket($rg_cache_socket, $ret = rg_socket($rg_cache_socket,
451 "UNSET " . $ns_var . "\n", $rg_cache_timeout, 1);
468 "UNSET F=$f " . $ns_var . "\n", $rg_cache_timeout, 1, $flags);
452 469 if ($ret === FALSE) if ($ret === FALSE)
453 470 break; break;
454 471
472 if ($flags & RG_SOCKET_NO_WAIT) {
473 $ret = TRUE;
474 break;
475 }
476
455 477 if (strncmp($ret, "NOT_FOUND", 9) == 0) if (strncmp($ret, "NOT_FOUND", 9) == 0)
456 478 break; break;
457 479
 
... ... function rg_cache_merge($ns_var, $list)
494 516 if ($rg_cache_enable === FALSE) if ($rg_cache_enable === FALSE)
495 517 break; break;
496 518
497 $c = rg_socket($rg_cache_socket, "MERGE " . $ns_var . "="
498 . rg_cache_prepare($list) . "\n", $rg_cache_timeout, 1);
519 $c = rg_socket($rg_cache_socket, "MERGE F= " . $ns_var . "="
520 . rg_cache_prepare($list) . "\n", $rg_cache_timeout, 1, 0);
499 521 if ($c === FALSE) if ($c === FALSE)
500 522 break; break;
501 523
File inc/dispatch/dispatch.php changed (mode: 100644) (index 98cea07..eebcc18)
... ... case 'logout':
13 13 if (!rg_valid_referer()) if (!rg_valid_referer())
14 14 rg_log("Invalid referer"); rg_log("Invalid referer");
15 15
16 if (!rg_token_valid($db, $rg, TRUE))
16 if (!rg_token_valid($db, $rg, 'logout', TRUE))
17 17 break; break;
18 18
19 19 rg_user_set_last_seen($db, $rg['login_ui']['uid']); rg_user_set_last_seen($db, $rg['login_ui']['uid']);
File inc/events.inc.php changed (mode: 100644) (index 30d7be0..b9cc87a)
... ... function rg_event_signal_daemon($ev_id, $timeout)
72 72 else else
73 73 $buf = "NOTIFY " . $ev_id; $buf = "NOTIFY " . $ev_id;
74 74
75 $r = rg_socket($rg_event_socket, $buf, $timeout, 1);
75 $flags = 0;
76 if ($timeout === 0)
77 $flags |= RG_SOCKET_NO_WAIT;
78
79 $r = rg_socket($rg_event_socket, $buf, $timeout, 1, $flags);
76 80
77 81 rg_log_exit(); rg_log_exit();
78 82 return $r; return $r;
File inc/feedback/suggestion.php changed (mode: 100644) (index 783d16c..d8613c9)
... ... while (1) {
19 19 break; break;
20 20 } }
21 21
22 if (!rg_token_valid($db, $rg, FALSE)) {
22 if (!rg_token_valid($db, $rg, 'suggestion', FALSE)) {
23 23 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
24 24 break; break;
25 25 } }
 
... ... while (1) {
43 43
44 44 $rg['suggestion'] = $suggestion; $rg['suggestion'] = $suggestion;
45 45 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
46 $rg['rg_form_token'] = rg_token_get($db, $rg);
46 $rg['rg_form_token'] = rg_token_get($db, $rg, 'suggestion');
47 47 $_suggestion .= rg_template("suggestion.html", $rg, TRUE /* xss */); $_suggestion .= rg_template("suggestion.html", $rg, TRUE /* xss */);
48 48
49 49 ?> ?>
File inc/keys.inc.php changed (mode: 100644) (index dc167c4..ecdb7b8)
... ... function rg_keys_regen($db)
542 542 break; break;
543 543 } }
544 544
545 rg_cache_set("key::last_regen_time", $now);
545 rg_cache_set("key::last_regen_time", $now, RG_SOCKET_NO_WAIT);
546 546
547 547 $ret = TRUE; $ret = TRUE;
548 548 break; break;
File inc/log.inc.php changed (mode: 100644) (index 81a7308..387f329)
... ... function rg_log($str)
93 93 // We insert some spaces based on backtrace len // We insert some spaces based on backtrace len
94 94 $spaces = ""; $spaces = "";
95 95 for ($i = 0; $i < $rg_log_level; $i++) for ($i = 0; $i < $rg_log_level; $i++)
96 $spaces .= " ";
96 $spaces .= ' ';
97 97
98 98 $t = gettimeofday(); $t = gettimeofday();
99 99
100 $buf0 = gmdate("Y-m-d H:i:s", $t['sec']) . "." . sprintf("%03u", $t['usec'] / 1000);
101 if (strcmp($rg_log_sid, "000000") != 0)
100 $buf0 = gmdate('Y-m-d H:i:s', $t['sec']) . "." . sprintf('%03u', $t['usec'] / 1000);
101 if (strcmp($rg_log_sid, '000000') != 0)
102 102 $buf0 .= " " . $rg_log_sid; $buf0 .= " " . $rg_log_sid;
103 103 $buf = ""; $buf = "";
104 $str = preg_replace_callback('/[^\pL\pN\pP\pS \t]/uU', "rg_callback_hexa", $str);
105 $buf .= $buf0 . " " . $spaces . $str . "\n";
104 $str = preg_replace_callback('/[^\pL\pN\pP\pS \t]/uU', 'rg_callback_hexa', $str);
105 $buf .= $buf0 . ' ' . $spaces . $str . "\n";
106 106
107 107 $rg_log_buf .= $buf; $rg_log_buf .= $buf;
108 108
 
... ... function rg_log_exit()
251 251 { {
252 252 global $rg_log_level; global $rg_log_level;
253 253
254 if ($rg_log_level == 0)
255 rg_internal_error('rg_log_exit called with level 0');
256
254 257 $rg_log_level--; $rg_log_level--;
255 258 } }
256 259
File inc/login/login.php changed (mode: 100644) (index efe460b..cc23c71)
... ... while ($rg['doit'] == 1) {
15 15 break; break;
16 16 } }
17 17
18 if (!rg_token_valid($db, $rg, FALSE)) {
18 if (!rg_token_valid($db, $rg, 'login', FALSE)) {
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);
40 $rg['rg_form_token'] = rg_token_get($db, $rg, 'login');
41 41 $_login .= rg_template("user/login.html", $rg, TRUE /* xss */); $_login .= rg_template("user/login.html", $rg, TRUE /* xss */);
42 42 ?> ?>
File inc/plan.inc.php changed (mode: 100644) (index c7bcece..6690ce9)
... ... function rg_plan_edit($db, $d)
81 81 $d['id'] = $row['id']; $d['id'] = $row['id'];
82 82
83 83 // invalidate cache // invalidate cache
84 rg_cache_unset("plan::list");
84 rg_cache_unset('plan::list', RG_SOCKET_NO_WAIT);
85 85
86 86 $ret = $row['id']; $ret = $row['id'];
87 87 break; break;
 
... ... function rg_plan_remove($db, $list)
117 117 rg_sql_free_result($res); rg_sql_free_result($res);
118 118
119 119 // invalidate cache // invalidate cache
120 rg_cache_unset("plan::list");
120 rg_cache_unset('plan::list', RG_SOCKET_NO_WAIT);
121 121
122 122 $ret = TRUE; $ret = TRUE;
123 123 break; break;
 
... ... function rg_plan_list($db)
162 162 } }
163 163 rg_sql_free_result($res); rg_sql_free_result($res);
164 164
165 rg_cache_set("plan::list", $ret);
165 rg_cache_set("plan::list", $ret, RG_SOCKET_NO_WAIT);
166 166 break; break;
167 167 } }
168 168
 
... ... function rg_plan_list_high_level($db, $rg)
250 250 break; break;
251 251 } }
252 252
253 if (!rg_token_valid($db, $rg, FALSE)) {
253 if (!rg_token_valid($db, $rg, 'plan_list', FALSE)) {
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)
273 273 return rg_template("admin/plans/list_err.html", $rg, TRUE /* xss */); return rg_template("admin/plans/list_err.html", $rg, TRUE /* xss */);
274 274 } }
275 275
276 $rg['rg_form_token'] = rg_token_get($db, $rg);
276 $rg['rg_form_token'] = rg_token_get($db, $rg, 'plan_list');
277 277 $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg); $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg);
278 278 $ret .= rg_template_table("admin/plans/list", $list, $rg); $ret .= rg_template_table("admin/plans/list", $list, $rg);
279 279 return $ret; return $ret;
 
... ... function rg_plan_edit_high_level($db, &$rg)
342 342 break; break;
343 343 } }
344 344
345 if (!rg_token_valid($db, $rg, FALSE)) {
345 if (!rg_token_valid($db, $rg, 'plan_edit_hl', FALSE)) {
346 346 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
347 347 break; break;
348 348 } }
 
... ... function rg_plan_edit_high_level($db, &$rg)
361 361 if ($load_form) { if ($load_form) {
362 362 $rg['pi'] = $pi; $rg['pi'] = $pi;
363 363 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
364 $rg['rg_form_token'] = rg_token_get($db, $rg);
364 $rg['rg_form_token'] = rg_token_get($db, $rg, 'plan_edit_hl');
365 365 $ret .= rg_template("admin/plans/add_edit.html", $rg, TRUE /* xss */); $ret .= rg_template("admin/plans/add_edit.html", $rg, TRUE /* xss */);
366 366 } }
367 367
File inc/repo.inc.php changed (mode: 100644) (index 3706700..a13e3cb)
... ... function rg_repo_info($db, $repo_id, $uid, $repo_name)
708 708 } }
709 709 //rg_log_ml("CHECK: ret=" . print_r($ret, TRUE)); //rg_log_ml("CHECK: ret=" . print_r($ret, TRUE));
710 710
711 rg_cache_set("repo_by_id::$repo_id", $ret);
711 rg_cache_set("repo_by_id::$repo_id", $ret, RG_SOCKET_NO_WAIT);
712 712
713 713 if ($ret['exists'] == 1) if ($ret['exists'] == 1)
714 714 rg_cache_set("repo_by_name::$uid::" . $ret['name'], rg_cache_set("repo_by_name::$uid::" . $ret['name'],
715 $ret['repo_id']);
715 $ret['repo_id'], RG_SOCKET_NO_WAIT);
716 716
717 717 break; break;
718 718 } }
 
... ... function rg_repo_delete($db, $repo_id, $ui)
769 769 } }
770 770 rg_event_signal_daemon("", 0); rg_event_signal_daemon("", 0);
771 771
772 rg_cache_unset("repo_by_id::$repo_id");
773 rg_cache_unset("repo_by_name::" . $ui['uid'] . "::" . $ri['name']);
772 rg_cache_unset('repo_by_id::' . $repo_id, RG_SOCKET_NO_WAIT);
773 rg_cache_unset('repo_by_name::' . $ui['uid']
774 . '::' . $ri['name'], RG_SOCKET_NO_WAIT);
774 775
775 776 $ret = TRUE; $ret = TRUE;
776 777 break; break;
 
... ... function rg_repo_lookup_by_old_name($db, $uid, $old_name)
816 817 else else
817 818 $ret = $row['repo_id']; $ret = $row['repo_id'];
818 819
819 rg_cache_set("repo_by_old_name::$uid::$old_name", $ret);
820 rg_cache_set("repo_by_old_name::$uid::$old_name", $ret, RG_SOCKET_NO_WAIT);
820 821 break; break;
821 822 } }
822 823
 
... ... function rg_repo_insert_rename($db, $uid, $repo_id, $old_name)
863 864 break; break;
864 865 } }
865 866
866 rg_cache_set("repo_by_name::$uid::$old_name", $repo_id);
867 rg_cache_set("repo_by_name::$uid::$old_name", $repo_id, RG_SOCKET_NO_WAIT);
867 868
868 869 $ret = TRUE; $ret = TRUE;
869 870 break; break;
 
... ... function rg_repo_edit($db, $login_ui, &$new)
1008 1009
1009 1010 $new['ok'] = 1; $new['ok'] = 1;
1010 1011 $new['exists'] = 1; $new['exists'] = 1;
1011 rg_cache_set("repo_by_id::" . $new['repo_id'], $new);
1012 rg_cache_set("repo_by_id::" . $new['repo_id'], $new, RG_SOCKET_NO_WAIT);
1012 1013 rg_cache_set("repo_by_name::" . $login_ui['uid'] . "::" rg_cache_set("repo_by_name::" . $login_ui['uid'] . "::"
1013 . $new['name'], $new['repo_id']);
1014 . $new['name'], $new['repo_id'], RG_SOCKET_NO_WAIT);
1014 1015
1015 1016 rg_event_signal_daemon("", 0); rg_event_signal_daemon("", 0);
1016 1017
 
... ... function rg_repo_admin_rights($db, $rg, $type)
1265 1266
1266 1267 $delete = rg_var_bool("delete"); $delete = rg_var_bool("delete");
1267 1268 while ($delete == 1) { while ($delete == 1) {
1269 if (!rg_valid_referer()) {
1270 $errmsg[] = "invalid referer; try again";
1271 break;
1272 }
1273
1274 if (!rg_token_valid($db, $rg, 'repo_admin_rights', FALSE)) {
1275 $errmsg[] = "invalid token; try again";
1276 break;
1277 }
1278
1268 1279 $list = rg_var_uint("rights_delete_ids"); $list = rg_var_uint("rights_delete_ids");
1269 1280 if (empty($list)) { if (empty($list)) {
1270 1281 $list_errmsg[] = "please select at least one item"; $list_errmsg[] = "please select at least one item";
 
... ... function rg_repo_admin_rights($db, $rg, $type)
1316 1327 break; break;
1317 1328 } }
1318 1329
1319 if (!rg_token_valid($db, $rg, FALSE)) {
1330 if (!rg_token_valid($db, $rg, 'repo_admin_rights', FALSE)) {
1320 1331 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1321 1332 break; break;
1322 1333 } }
 
... ... function rg_repo_admin_rights($db, $rg, $type)
1359 1370 $rg = rg_array_merge($rg, '', $a); $rg = rg_array_merge($rg, '', $a);
1360 1371 } }
1361 1372
1362 $rg['rg_form_token'] = rg_token_get($db, $rg);
1373 $rg['rg_form_token'] = rg_token_get($db, $rg, 'repo_admin_rights');
1363 1374 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1364 1375 $rg['HTML:list_errmsg'] = rg_template_errmsg($list_errmsg); $rg['HTML:list_errmsg'] = rg_template_errmsg($list_errmsg);
1365 1376 $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)
1425 1436 break; break;
1426 1437 } }
1427 1438
1428 if (!rg_token_valid($db, $rg, FALSE)) {
1439 if (!rg_token_valid($db, $rg, 'repo_admin_delete', FALSE)) {
1429 1440 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1430 1441 break; break;
1431 1442 } }
 
... ... function rg_repo_admin_delete($db, $rg)
1446 1457
1447 1458 if ($show_form == 1) { if ($show_form == 1) {
1448 1459 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1449 $rg['rg_form_token'] = rg_token_get($db, $rg);
1460 $rg['rg_form_token'] = rg_token_get($db, $rg, 'repo_admin_delete');
1450 1461 $ret .= rg_template("user/repo/delete/sure.html", $rg, TRUE /* xss */); $ret .= rg_template("user/repo/delete/sure.html", $rg, TRUE /* xss */);
1451 1462 } }
1452 1463
 
... ... function rg_repo_edit_high_level($db, &$rg)
1509 1520 break; break;
1510 1521 } }
1511 1522
1512 $rg['ri']['repo_id'] = rg_var_uint("repo_id");
1513 $rg['ri']['master'] = rg_var_uint("master");
1514 $rg['ri']['name'] = rg_var_str("name"); // TODO: filter name!
1515 $rg['ri']['max_commit_size'] = rg_var_uint("max_commit_size");
1516 $rg['ri']['description'] = trim(rg_var_str("description"));
1517 $rg['ri']['public'] = rg_var_bool("public");
1518 $rg['ri']['license'] = trim(rg_var_str("license"));
1523 $rg['ri']['repo_id'] = rg_var_uint('repo_id');
1524 $rg['ri']['master'] = rg_var_uint('master');
1525 $rg['ri']['name'] = rg_var_str('name'); // TODO: filter name!
1526 $rg['ri']['max_commit_size'] = rg_var_uint('max_commit_size');
1527 $rg['ri']['description'] = trim(rg_var_str('description'));
1528 $rg['ri']['public'] = rg_var_bool('public');
1529 $rg['ri']['license'] = trim(rg_var_str('license'));
1519 1530 rg_repo_cosmetic($rg['ri']); rg_repo_cosmetic($rg['ri']);
1520 1531 //rg_log_ml("CHECK: after repo edit: rg[ri]=" . print_r($rg['ri'], TRUE)); //rg_log_ml("CHECK: after repo edit: rg[ri]=" . print_r($rg['ri'], TRUE));
1521 1532
 
... ... function rg_repo_edit_high_level($db, &$rg)
1524 1535 break; break;
1525 1536 } }
1526 1537
1527 if (!rg_token_valid($db, $rg, FALSE)) {
1538 if (!rg_token_valid($db, $rg, 'repo_edit_hl', FALSE)) {
1528 1539 // TODO: replace all of these with a template // TODO: replace all of these with a template
1529 1540 $errmsg[] = "invalid token; try again."; $errmsg[] = "invalid token; try again.";
1530 1541 break; break;
 
... ... function rg_repo_edit_high_level($db, &$rg)
1559 1570 } }
1560 1571
1561 1572 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1562 $rg['rg_form_token'] = rg_token_get($db, $rg);
1573 $rg['rg_form_token'] = rg_token_get($db, $rg, 'repo_edit_hl');
1563 1574 $hints = array(); $hints = array();
1564 1575 $hints[]['HTML:hint'] = rg_template("hints/repo/create_repo.html", $rg, TRUE /* xss */); $hints[]['HTML:hint'] = rg_template("hints/repo/create_repo.html", $rg, TRUE /* xss */);
1565 1576 $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/rights.inc.php changed (mode: 100644) (index ebab54f..39227be)
... ... function rg_rights_get($db, $obj_id, $type, $owner, $uid, $right_id)
325 325 $r = array_merge($r, $x); $r = array_merge($r, $x);
326 326
327 327 // We store the big list // We store the big list
328 rg_cache_set($key, $r);
328 rg_cache_set($key, $r, RG_SOCKET_NO_WAIT);
329 329 } else { } else {
330 330 rg_log("CHECK: rights returned from cache for key $key"); rg_log("CHECK: rights returned from cache for key $key");
331 331 } }
 
... ... function rg_rights_set($db, $type, $a)
399 399
400 400 // invalidate cache (TODO: optimize by inserting in list and reorder) // invalidate cache (TODO: optimize by inserting in list and reorder)
401 401 $key = "rights_by_obj_id::" . $a['obj_id'] . "::" . $a['type']; $key = "rights_by_obj_id::" . $a['obj_id'] . "::" . $a['type'];
402 rg_cache_unset($key);
402 rg_cache_unset($key, RG_SOCKET_NO_WAIT);
403 403
404 404 $ret = TRUE; $ret = TRUE;
405 405 break; break;
 
... ... function rg_rights_delete_list($db, $type, $obj_id, $list)
757 757 } }
758 758
759 759 // invalidate cache; TODO: this is the best way? // invalidate cache; TODO: this is the best way?
760 rg_cache_unset("rights_by_obj_id::$obj_id::$type");
760 rg_cache_unset('rights_by_obj_id::' . $obj_id
761 . '::' . $type, RG_SOCKET_NO_WAIT);
761 762
762 763 break; break;
763 764 } }
File inc/sess.inc.php changed (mode: 100644) (index 4bb845d..95e92a4)
... ... function rg_sess_add($db, $uid, $sid, $session_time, $lock_ip)
37 37 rg_sql_free_result($res); rg_sql_free_result($res);
38 38
39 39 $params['last_db_write'] = $now; $params['last_db_write'] = $now;
40 rg_cache_set("sess::" . $sid, $params);
40 rg_cache_set("sess::" . $sid, $params, RG_SOCKET_NO_WAIT);
41 41
42 42 $ret = TRUE; $ret = TRUE;
43 43 break; break;
 
... ... function rg_sess_valid($db, $sid)
72 72 if ($rows > 0) { if ($rows > 0) {
73 73 $r = rg_sql_fetch_array($res); $r = rg_sql_fetch_array($res);
74 74 $r['last_db_write'] = $r['expire'] - $r['session_time']; $r['last_db_write'] = $r['expire'] - $r['session_time'];
75 rg_cache_set("sess::" . $sid, $r);
75 rg_cache_set("sess::" . $sid, $r, RG_SOCKET_NO_WAIT);
76 76 } }
77 77 rg_sql_free_result($res); rg_sql_free_result($res);
78 78 } }
 
... ... function rg_sess_update($db, $sess)
140 140 rg_sql_free_result($res); rg_sql_free_result($res);
141 141 } }
142 142
143 rg_cache_set("sess::" . $sess['sid'], $sess);
143 rg_cache_set("sess::" . $sess['sid'], $sess, RG_SOCKET_NO_WAIT);
144 144
145 145 $ret = TRUE; $ret = TRUE;
146 146 break; break;
 
... ... function rg_sess_destroy($db, $sid, &$ui)
171 171 rg_sql_free_result($res); rg_sql_free_result($res);
172 172
173 173 // Delete all tokens associated with this session // Delete all tokens associated with this session
174 rg_token_delete($db, $sid, "");
174 rg_token_delete($db, $sid, '');
175 175
176 176 $ui = array(); $ui = array();
177 177 $ui['uid'] = 0; $ui['uid'] = 0;
178 178 $ui['is_admin'] = 0; $ui['is_admin'] = 0;
179 179
180 rg_cache_unset("sess::" . $sid);
180 rg_cache_unset('sess' . '::' . $sid, RG_SOCKET_NO_WAIT);
181 181
182 182 $ret = TRUE; $ret = TRUE;
183 183 break; break;
File inc/state.inc.php changed (mode: 100644) (index 983d57b..1159774)
... ... function rg_state_get($db, $var)
56 56 } else { } else {
57 57 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
58 58 $ret = $row['value']; $ret = $row['value'];
59 rg_cache_set("state::" . $var, $ret);
59 rg_cache_set("state::" . $var, $ret, RG_SOCKET_NO_WAIT);
60 60 } }
61 61 rg_sql_free_result($res); rg_sql_free_result($res);
62 62
 
... ... function rg_state_set($db, $var, $value)
116 116 } }
117 117 rg_sql_free_result($res); rg_sql_free_result($res);
118 118
119 rg_cache_set("state::" . $var, $value);
119 rg_cache_set("state::" . $var, $value, RG_SOCKET_NO_WAIT);
120 120
121 121 $ret = TRUE; $ret = TRUE;
122 122 break; break;
File inc/token.inc.php changed (mode: 100644) (index 3f49644..f7e5774)
2 2 require_once($INC . "/util.inc.php"); require_once($INC . "/util.inc.php");
3 3 require_once($INC . "/log.inc.php"); require_once($INC . "/log.inc.php");
4 4 require_once($INC . "/sql.inc.php"); require_once($INC . "/sql.inc.php");
5 require_once($INC . "/cache.inc.php");
5 6 require_once($INC . "/prof.inc.php"); require_once($INC . "/prof.inc.php");
6 7
7 8 $rg_token_error = ""; $rg_token_error = "";
 
... ... function rg_token_get_master($db)
66 67
67 68 $ret = FALSE; $ret = FALSE;
68 69 while (1) { while (1) {
69 $key = rg_state_get($db, "token_key");
70 $key = rg_state_get($db, 'token_key');
70 71 if ($key === FALSE) { if ($key === FALSE) {
71 72 rg_token_set_error("cannot get token_key:" rg_token_set_error("cannot get token_key:"
72 73 . " " . rg_state_error()); . " " . rg_state_error());
 
... ... function rg_token_get_master($db)
75 76
76 77 if (empty($key)) { if (empty($key)) {
77 78 $key = rg_id(32); $key = rg_id(32);
78 $r = rg_state_set($db, "token_key", $key);
79 $r = rg_state_set($db, 'token_key', $key);
79 80 if ($r !== TRUE) { if ($r !== TRUE) {
80 81 rg_token_set_error("cannot set state:" rg_token_set_error("cannot set state:"
81 82 . " " . rg_state_error()); . " " . rg_state_error());
 
... ... function rg_token_get_master($db)
94 95
95 96 /* /*
96 97 * Returns TRUE if the token is valid * Returns TRUE if the token is valid
98 * @double_allowed - if TRUE, we will not mark the token as used
99 * (for example, logout token does not have to be marked as used)
97 100 */ */
98 function rg_token_valid($db, $rg, $double_allowed)
101 function rg_token_valid($db, $rg, $tag, $double_allowed)
99 102 { {
100 103 rg_prof_start("token_valid"); rg_prof_start("token_valid");
101 104 rg_log_enter("token_valid: sid=" . $rg['sid'] . " token=" . $rg['token'] rg_log_enter("token_valid: sid=" . $rg['sid'] . " token=" . $rg['token']
102 . " ua=" . $rg['ua']);
105 . " ua=" . $rg['ua'] . ' tag=' . $tag);
103 106
104 107 $ret = FALSE; $ret = FALSE;
105 108 while (1) { while (1) {
106 $ua_hash = substr(sha512($rg['ua']), 0, 8);
107
108 109 $len = strlen($rg['token']); $len = strlen($rg['token']);
109 if ($len != 32) {
110 if ($len < 32) {
110 111 rg_token_set_error("invalid token"); rg_token_set_error("invalid token");
111 112 rg_security_violation_no_exit("invalid token ($len != 32)"); rg_security_violation_no_exit("invalid token ($len != 32)");
112 113 break; break;
113 114 } }
115 $rg['token'] = substr($rg['token'], 0, 32);
114 116
117 // We have to check first because of ua
115 118 $key = rg_token_get_master($db); $key = rg_token_get_master($db);
116 119 if ($key === FALSE) if ($key === FALSE)
117 120 break; break;
 
... ... function rg_token_valid($db, $rg, $double_allowed)
119 122 $rand = substr($rg['token'], 0, 16); $rand = substr($rg['token'], 0, 16);
120 123 $sign = substr($rg['token'], 16, 16); $sign = substr($rg['token'], 16, 16);
121 124
122 $data = $rand . $rg['sid'] . $ua_hash;
123 $hash = hash_hmac("sha512", $data, $key);
125 $data = $rand . $rg['sid'] . $rg['ua'] . $tag;
126 $hash = hash_hmac('sha512', $data, $key);
124 127 if ($hash === FALSE) { if ($hash === FALSE) {
125 128 rg_token_set_error("cannot compute hmac"); rg_token_set_error("cannot compute hmac");
126 129 break; break;
 
... ... function rg_token_valid($db, $rg, $double_allowed)
134 137 break; break;
135 138 } }
136 139
140 $ukey = 'sess' . '::' . $rg['sid'] . '::' . 'used_tokens'
141 . '::' . $rg['token'];
142 $c = rg_cache_get($ukey);
143 if ($c === '1') {
144 rg_token_set_error("token already used");
145 break;
146 }
147
148 $params = array("sid" => $rg['sid'],
149 "token" => $rg['token'],
150 "expire" => time() + 24 * 3600);
151
152 if ($c === FALSE) {
153 // We check to see if token was already used
154 $sql = "SELECT 1 FROM tokens"
155 . " WHERE sid = @@sid@@"
156 . " AND token = @@token@@";
157 $res = rg_sql_query_params($db, $sql, $params);
158 if ($res === FALSE) {
159 rg_token_set_error("cannot check if token is used"
160 . " (" . rg_sql_error() . ")");
161 break;
162 }
163 $rows = rg_sql_num_rows($res);
164 rg_sql_free_result($res);
165 if ($rows == 1) {
166 rg_token_set_error("token already used");
167 break;
168 }
169 }
170
137 171 if (strncmp($rg['sid'], "X", 1) == 0) { if (strncmp($rg['sid'], "X", 1) == 0) {
138 172 // We have a pre-login session: we do not have to mark // We have a pre-login session: we do not have to mark
139 173 // the token as used. // the token as used.
 
... ... function rg_token_valid($db, $rg, $double_allowed)
146 180 break; break;
147 181 } }
148 182
149 $params = array("sid" => $rg['sid'],
150 "token" => $rg['token'],
151 "expire" => time() + 24 * 3600);
152
153 // We check to see if token was already used
154 $sql = "SELECT 1 FROM tokens"
155 . " WHERE sid = @@sid@@"
156 . " AND token = @@token@@";
157 $res = rg_sql_query_params($db, $sql, $params);
158 if ($res === FALSE) {
159 rg_token_set_error("cannot check if token is used"
160 . " (" . rg_sql_error() . ")");
161 break;
162 }
163 $rows = rg_sql_num_rows($res);
164 rg_sql_free_result($res);
165 if ($rows == 1) {
166 rg_token_set_error("token already used");
167 break;
168 }
183 // Unset cached token to generate a new one for this tag
184 $tkey = 'sess' . '::' . $rg['sid'] . '::' . 'token'
185 . '::' . $tag;
186 rg_cache_unset($tkey, RG_SOCKET_NO_WAIT);
169 187
170 188 $sql = "INSERT INTO tokens (sid, token, expire)" $sql = "INSERT INTO tokens (sid, token, expire)"
171 189 . " VALUES (@@sid@@, @@token@@, @@expire@@)"; . " VALUES (@@sid@@, @@token@@, @@expire@@)";
 
... ... function rg_token_valid($db, $rg, $double_allowed)
177 195 } }
178 196 rg_sql_free_result($res); rg_sql_free_result($res);
179 197
198 // This is an optimization to not look next time in db
199 rg_cache_set($ukey, '1', RG_SOCKET_NO_WAIT);
200
180 201 $ret = TRUE; $ret = TRUE;
181 202 break; break;
182 203 } }
 
... ... function rg_token_valid($db, $rg, $double_allowed)
188 209
189 210 /* /*
190 211 * Returns a token to be used on a form/url * Returns a token to be used on a form/url
191 * We generate only one per form, but multiple per session.
212 * We generate only one per form (tag is the id), but multiple per session.
192 213 */ */
193 $rg_token = FALSE;
194 function rg_token_get($db, $rg)
214 function rg_token_get($db, $rg, $tag)
195 215 { {
196 global $rg_token;
197
198 rg_log_enter("token_get: sid=" . $rg['sid']);
216 rg_log_enter('token_get: sid=' . $rg['sid'] . ' tag=' . $tag
217 . 'ua=' . $rg['ua']);
199 218
200 219 $ret = FALSE; $ret = FALSE;
201 220 while (1) { while (1) {
202 221 if (empty($rg['sid'])) if (empty($rg['sid']))
203 222 break; break;
204 223
205 if ($rg_token !== FALSE) {
206 $ret = $rg_token;
224 $key = 'sess' . '::' . $rg['sid'] . '::' . 'token' . '::' . $tag;
225 $c = rg_cache_get($key);
226 if ($c !== FALSE) {
227 $ret = $c;
207 228 break; break;
208 229 } }
209 230
210 $key = rg_token_get_master($db);
211 if ($key === FALSE)
231 $sign_key = rg_token_get_master($db);
232 if ($sign_key === FALSE)
212 233 break; break;
213 234
214 235 $rand = rg_id(16); $rand = rg_id(16);
215 $ua_hash = substr(sha512($rg['ua']), 0, 8);
216
217 $data = $rand . $rg['sid'] . $ua_hash;
218 $sign = hash_hmac("sha512", $data, $key);
236 $data = $rand . $rg['sid'] . $rg['ua'] . $tag;
237 $sign = hash_hmac('sha512', $data, $sign_key);
219 238 if ($sign === FALSE) { if ($sign === FALSE) {
220 239 rg_token_set_error("cannot compute hmac"); rg_token_set_error("cannot compute hmac");
221 240 break; break;
222 241 } }
223 242 $sign = substr($sign, 0, 16); $sign = substr($sign, 0, 16);
224 $rg_token = $rand . $sign;
225 $ret = $rg_token;
243 $ret = $rand . $sign;
244 $ret2 = $ret;
245
246 if ($rg['debug'])
247 $ret2 .= ':' . $tag;
248
249 rg_cache_set($key, $ret2, RG_SOCKET_NO_WAIT);
250
251 // Optimization to not look in database next time
252 $key = 'sess' . '::' . $rg['sid'] . '::' . 'used_tokens'
253 . '::' . $ret;
254 rg_cache_set($key, '0', RG_SOCKET_NO_WAIT);
255
256 $ret = $ret2;
226 257 break; break;
227 258 } }
228 259
File inc/user.inc.php changed (mode: 100644) (index 7e935da..921d99d)
... ... function rg_user_lookup_by_old_name($db, $old_name)
267 267 else else
268 268 $ret = $row['uid']; $ret = $row['uid'];
269 269
270 rg_cache_set("old_name::" . $old_name, $ret);
270 rg_cache_set("old_name::" . $old_name, $ret, RG_SOCKET_NO_WAIT);
271 271 break; break;
272 272 } }
273 273
 
... ... function rg_user_insert_rename($db, $uid, $old_name)
311 311 break; break;
312 312 } }
313 313
314 rg_cache_set("old_name::" . $old_name, $uid);
314 rg_cache_set("old_name::" . $old_name, $uid, RG_SOCKET_NO_WAIT);
315 315
316 316 $ret = TRUE; $ret = TRUE;
317 317 break; break;
 
... ... function rg_user_edit($db, $d)
506 506 // invalidate cache (because we may not have the password) // invalidate cache (because we may not have the password)
507 507 // TODO: but, we can do a merge! // TODO: but, we can do a merge!
508 508 if ($d['uid'] > 0) if ($d['uid'] > 0)
509 rg_cache_unset("user::" . $d['uid']);
509 rg_cache_unset('user::' . $d['uid'], RG_SOCKET_NO_WAIT);
510 510
511 511 if ($d['uid'] == 0) { // add if ($d['uid'] == 0) { // add
512 512 $event = array('category' => 2000, 'prio' => 50, $event = array('category' => 2000, 'prio' => 50,
 
... ... function rg_user_remove($db, $rg, $uid)
570 570 rg_sql_free_result($res); rg_sql_free_result($res);
571 571
572 572 // invalidate cache // invalidate cache
573 rg_cache_unset("user::" . $uid);
573 rg_cache_unset('user::' . $uid, RG_SOCKET_NO_WAIT);
574 574
575 575 $ret = TRUE; $ret = TRUE;
576 576 break; break;
 
... ... function rg_user_info($db, $uid, $user, $email)
652 652 $ret = array_merge($ret, $row); $ret = array_merge($ret, $row);
653 653 $ret['exists'] = 1; $ret['exists'] = 1;
654 654
655 rg_cache_set("user::" . $ret['uid'], $ret);
656 rg_cache_set("username_to_uid::" . $ret['username'], $ret['uid']);
657 rg_cache_set("email_to_uid::" . $ret['email'], $ret['uid']);
655 rg_cache_set("user::" . $ret['uid'], $ret, RG_SOCKET_NO_WAIT);
656 rg_cache_set('username_to_uid::' . $ret['username'],
657 $ret['uid'], RG_SOCKET_NO_WAIT);
658 rg_cache_set('email_to_uid::' . $ret['email'], $ret['uid'],
659 RG_SOCKET_NO_WAIT);
658 660 break; break;
659 661 } }
660 662
 
... ... function rg_user_suspend($db, $rg, $uid, $op)
935 937 rg_sql_free_result($res); rg_sql_free_result($res);
936 938
937 939 // update cache // update cache
938 rg_cache_set("user::" . $uid . "::suspended", $v);
940 // TODO: what if we cannot update?
941 rg_cache_set("user::" . $uid . "::suspended", $v, RG_SOCKET_NO_WAIT);
939 942
940 943 break; break;
941 944 } }
 
... ... function rg_user_make_admin($db, $rg, $uid, $op)
977 980 } }
978 981 rg_sql_free_result($res); rg_sql_free_result($res);
979 982
980 rg_cache_set("user::" . $uid . "::is_admin", 1);
983 rg_cache_set("user::" . $uid . "::is_admin", 1, RG_SOCKET_NO_WAIT);
981 984
982 985 $ret = TRUE; $ret = TRUE;
983 986 break; break;
 
... ... function rg_user_forgot_pass_uid($db, $token)
1133 1136 */ */
1134 1137 function rg_user_forgot_pass_mail_prepare($db, $email) function rg_user_forgot_pass_mail_prepare($db, $email)
1135 1138 { {
1136 rg_log("user_forgot_pass_mail_prepare: email=$email");
1139 rg_log_enter("user_forgot_pass_mail_prepare: email=$email");
1137 1140
1138 1141 $ret = array(); $ret = array();
1139 1142 $ret['ok'] = 0; $ret['ok'] = 0;
 
... ... function rg_user_set_pass($db, $uid, $pass)
1280 1283
1281 1284 // Because we may not have info about the user in cache, // Because we may not have info about the user in cache,
1282 1285 // we cannot do a merge. // we cannot do a merge.
1283 rg_cache_unset("user::$uid");
1286 rg_cache_unset('user::' . $uid, RG_SOCKET_NO_WAIT);
1284 1287
1285 1288 $ret = TRUE; $ret = TRUE;
1286 1289 break; break;
 
... ... function rg_user_confirm($db, $token)
1338 1341 } }
1339 1342 rg_sql_free_result($res); rg_sql_free_result($res);
1340 1343
1341 rg_cache_unset("user::" . $uid);
1344 rg_cache_unset('user::' . $uid, RG_SOCKET_NO_WAIT);
1342 1345
1343 1346 $ret = $uid; $ret = $uid;
1344 1347 break; break;
 
... ... function rg_user_edit_high_level($db, &$rg)
1490 1493 break; break;
1491 1494 } }
1492 1495
1493 if (!rg_token_valid($db, $rg, FALSE)) {
1496 if (!rg_token_valid($db, $rg, 'user_edit_hl', FALSE)) {
1494 1497 $errmsg[] = "invalid token; try again"; $errmsg[] = "invalid token; try again";
1495 1498 break; break;
1496 1499 } }
 
... ... function rg_user_edit_high_level($db, &$rg)
1518 1521 if (!empty($ui['pass'])) if (!empty($ui['pass']))
1519 1522 rg_security_violation_no_exit("User tried to" rg_security_violation_no_exit("User tried to"
1520 1523 . " change pass using 'edit info' page."); . " change pass using 'edit info' page.");
1521 $ui['pass'] = "";
1524 $ui['pass'] = '';
1522 1525 } }
1523 1526
1524 1527 $r = rg_user_edit($db, $ui); $r = rg_user_edit($db, $ui);
 
... ... function rg_user_edit_high_level($db, &$rg)
1543 1546 $rg['HTML:checkbox_rights'] = rg_rights_checkboxes("user", $rg['HTML:checkbox_rights'] = rg_rights_checkboxes("user",
1544 1547 "rights", $ui['rights']); "rights", $ui['rights']);
1545 1548 $rg['HTML:errmsg'] = rg_template_errmsg($errmsg); $rg['HTML:errmsg'] = rg_template_errmsg($errmsg);
1546 $rg['rg_form_token'] = rg_token_get($db, $rg);
1549 $rg['rg_form_token'] = rg_token_get($db, $rg, 'user_edit_hl');
1547 1550 $ret .= rg_template("user/add_edit.html", $rg, TRUE /* xss */); $ret .= rg_template("user/add_edit.html", $rg, TRUE /* xss */);
1548 1551 } }
1549 1552
File inc/user/keys/keys.php changed (mode: 100644) (index 51f5c31..b20dcf2)
... ... if (rg_var_uint("add") == 1) {
21 21 break; break;
22 22 } }
23 23
24 if (!rg_token_valid($db, $rg, FALSE)) {
24 if (!rg_token_valid($db, $rg, 'keys', FALSE)) {
25 25 $add_errmsg[] = "Invalid token. Try again."; $add_errmsg[] = "Invalid token. Try again.";
26 26 break; break;
27 27 } }
 
... ... if (rg_var_uint("add") == 1) {
42 42 break; break;
43 43 } }
44 44
45 if (!rg_token_valid($db, $rg, FALSE)) {
45 if (!rg_token_valid($db, $rg, 'keys', FALSE)) {
46 46 $del_errmsg[] = "Invalid token. Try again."; $del_errmsg[] = "Invalid token. Try again.";
47 47 break; break;
48 48 } }
 
... ... $rg['HTML:add_errmsg'] = rg_template_errmsg($add_errmsg);
66 66 $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg); $rg['HTML:del_errmsg'] = rg_template_errmsg($del_errmsg);
67 67
68 68 $rg['key'] = $key; $rg['key'] = $key;
69 $rg['rg_form_token'] = rg_token_get($db, $rg);
69 $rg['rg_form_token'] = rg_token_get($db, $rg, 'keys');
70 70 $rg['HTML:add_form'] = rg_template("user/keys/add.html", $rg, TRUE /* xss */); $rg['HTML:add_form'] = rg_template("user/keys/add.html", $rg, TRUE /* xss */);
71 71
72 72 $keys_list = rg_keys_list($db, $rg['login_ui']); $keys_list = rg_keys_list($db, $rg['login_ui']);
File inc/user/pass/pass.php changed (mode: 100644) (index 53fa336..294f98d)
... ... while (1) {
19 19 break; break;
20 20 } }
21 21
22 if (!rg_token_valid($db, $rg, FALSE)) {
22 if (!rg_token_valid($db, $rg, 'set_pass', FALSE)) {
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);
49 $rg['rg_form_token'] = rg_token_get($db, $rg, 'set_pass');
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/bug/main.php changed (mode: 100644) (index 4ab4e63..25642dd)
... ... case 'list':
27 27 break; break;
28 28 } }
29 29
30 if (!rg_token_valid($db, $rg, FALSE)) {
30 if (!rg_token_valid($db, $rg, 'remove_search', FALSE)) {
31 31 $_bug_body .= rg_warning("Error: invalid token; try again."); // TODO $_bug_body .= rg_warning("Error: invalid token; try again."); // TODO
32 32 break; break;
33 33 } }
 
... ... case 'list':
69 69 // Show remove for custom search // Show remove for custom search
70 70 // TODO: don't we check for uid also? Security problems? // TODO: don't we check for uid also? Security problems?
71 71 if (isset($filter['standard']) && ($filter['standard'] == 0)) { if (isset($filter['standard']) && ($filter['standard'] == 0)) {
72 $rg['rg_form_token'] = rg_token_get($db, $rg);
72 $rg['rg_form_token_tag'] = 'remove_search';
73 $rg['rg_form_token'] = rg_token_get($db, $rg, 'remove_search');
73 74 $rg['search_remove_errmsg'] = ""; $rg['search_remove_errmsg'] = "";
74 75 $_bug_body .= rg_template("repo/bug/search/remove.html", $rg, TRUE /* xss */); $_bug_body .= rg_template("repo/bug/search/remove.html", $rg, TRUE /* xss */);
75 76 } }
File inc/user/repo/bug/show/add_note.php changed (mode: 100644) (index 370366a..ef7b38f)
... ... while (1) {
18 18 break; break;
19 19 } }
20 20
21 if (!rg_token_valid($db, $rg, FALSE)) {
21 if (!rg_token_valid($db, $rg, 'note_add', FALSE)) {
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);
48 $rg['rg_form_token_tag'] = 'note_add';
49 $rg['rg_form_token'] = rg_token_get($db, $rg, 'note_add');
49 50 $rg['note'] = $note; $rg['note'] = $note;
50 51 $rg['HTML:note_add'] = rg_template("repo/bug/note_add.html", $rg, TRUE /* xss */); $rg['HTML:note_add'] = rg_template("repo/bug/note_add.html", $rg, TRUE /* xss */);
51 52 ?> ?>
File inc/user/repo/bug/show/show.php changed (mode: 100644) (index 9ad0863..98005dd)
... ... rg_log("FILE: /inc/user/repo/bug/show/show");
3 3
4 4 // TODO: security checks // TODO: security checks
5 5
6 $_bug_show = "";
6 $_bug_show = '';
7 7
8 $rg['rg_form_token'] = rg_token_get($db, $rg);
9 $rg['HTML:bug_edit'] = "";
8 $rg['HTML:bug_edit'] = '';
9 $rg['HTML:button_error'] = '';
10 10
11 11 $ibug = rg_bug_info($db, $rg['ri']['repo_id'], $rg['bug']['bug_id']); $ibug = rg_bug_info($db, $rg['ri']['repo_id'], $rg['bug']['bug_id']);
12 12 if ($ibug === FALSE) if ($ibug === FALSE)
 
... ... if ($ibug === FALSE)
15 15 $rg['bug'] = array_merge($rg['bug'], $ibug); $rg['bug'] = array_merge($rg['bug'], $ibug);
16 16
17 17 if ($ibug['exists'] != 1) { if ($ibug['exists'] != 1) {
18 $_bug_body .= rg_template("repo/bug/not_found.html", $rg, TRUE /* xss */);
18 $_bug_body .= rg_template("repo/bug/not_found.html", $rg, TRUE /*xss*/);
19 19 return; return;
20 20 } }
21 21
 
... ... $x['misc'] = '';
32 32 if ($ibug['deleted'] > 0) { if ($ibug['deleted'] > 0) {
33 33 $x['needed_rights'] = 'd'; $x['needed_rights'] = 'd';
34 34 if (rg_rights_allow($db, $x) !== TRUE) { if (rg_rights_allow($db, $x) !== TRUE) {
35 $_bug_body .= rg_template("repo/bug/deleted.html", $rg, TRUE /* xss */);
35 $_bug_body .= rg_template("repo/bug/deleted.html", $rg, TRUE /*xss*/);
36 36 return; return;
37 37 } }
38 38 } }
 
... ... if ($ibug['deleted'] > 0) {
40 40 // load labels // load labels
41 41 $labels = rg_bug_label_get($db, $rg['ri']['repo_id'], $rg['bug']['bug_id']); $labels = rg_bug_label_get($db, $rg['ri']['repo_id'], $rg['bug']['bug_id']);
42 42 if ($labels === FALSE) if ($labels === FALSE)
43 $rg['HTML:labels_html'] = "Cannot load labels!";
43 $rg['HTML:labels_html'] = rg_warning('Cannot load labels!', $rg);
44 44 else else
45 45 $rg['HTML:labels_html'] = rg_bug_label_html($db, $labels); $rg['HTML:labels_html'] = rg_bug_label_html($db, $labels);
46 46 $rg['bug']['labels'] = implode(" ", $labels); $rg['bug']['labels'] = implode(" ", $labels);
47 47
48 48 // edit // edit
49 $rg['HTML:edit_form'] = rg_template("repo/bug/b_edit.html", $rg, TRUE /* xss */);
49 $rg['rg_form_token_tag'] = 'bug_edit_hl';
50 $rg['rg_form_token'] = rg_token_get($db, $rg, 'bug_edit_hl');
51 $rg['HTML:edit_form'] = rg_template("repo/bug/b_edit.html", $rg, TRUE /*xss*/);
50 52 if (rg_var_uint("edit") == 1) if (rg_var_uint("edit") == 1)
51 53 $rg['HTML:bug_edit'] = rg_bug_edit_high_level($db, $rg); $rg['HTML:bug_edit'] = rg_bug_edit_high_level($db, $rg);
52 54
53 55 // close/re-open // close/re-open
54 $close_reopen_error = "";
56 $close_reopen_error = '';
55 57 while (1) { while (1) {
56 58 if (rg_var_uint("close_reopen") != 1) if (rg_var_uint("close_reopen") != 1)
57 59 break; break;
 
... ... while (1) {
62 64 if ($ibug['state'] == 1) { // reopen if ($ibug['state'] == 1) { // reopen
63 65 $x['needed_rights'] = 'r'; $x['needed_rights'] = 'r';
64 66 if (rg_rights_allow($db, $x) !== TRUE) { if (rg_rights_allow($db, $x) !== TRUE) {
65 rg_template("repo/bug/deny_reopen.html", $rg, TRUE /* xss */);
67 rg_template("repo/bug/deny_reopen.html", $rg, TRUE /*xss*/);
66 68 break; break;
67 69 } }
68 70 } else { // close } else { // close
69 71 $x['needed_rights'] = 'C'; $x['needed_rights'] = 'C';
70 72 if (rg_rights_allow($db, $x) !== TRUE) { if (rg_rights_allow($db, $x) !== TRUE) {
71 rg_template("repo/bug/deny_close.html", $rg, TRUE /* xss */);
73 rg_template("repo/bug/deny_close.html", $rg, TRUE /*xss*/);
72 74 break; break;
73 75 } }
74 76 } }
75 77
76 78 if (!rg_valid_referer()) { if (!rg_valid_referer()) {
77 $close_reopen_error = "Invalid referer; try again";
79 $close_reopen_error = rg_warning('Invalid referer; try again', $rg);
78 80 break; break;
79 81 } }
80 82
81 if (!rg_token_valid($db, $rg, FALSE)) {
82 $close_reopen_error = "Invalid token. Try again.";
83 if (!rg_token_valid($db, $rg, 'close_reopen', FALSE)) {
84 $close_reopen_error = rg_warning('Invalid token. Try again.', $rg);
83 85 break; break;
84 86 } }
85 87
86 88 $ret = rg_bug_edit($db, $rg['login_ui'], $rg['ri'], $ibug); $ret = rg_bug_edit($db, $rg['login_ui'], $rg['ri'], $ibug);
87 89 if ($ret === FALSE) { if ($ret === FALSE) {
88 $close_reopen_error = "Cannot edit bug (" . rg_bug_error() . ")";
90 $close_reopen_error = rg_warning('Cannot edit bug (' . rg_bug_error() . ')', $rg);
89 91 break; break;
90 92 } }
91 93
 
... ... if ($ibug['state'] == 1)
96 98 $t = "repo/bug/b_close.html"; $t = "repo/bug/b_close.html";
97 99 else else
98 100 $t = "repo/bug/b_reopen.html"; $t = "repo/bug/b_reopen.html";
99 $rg['HTML:close_form'] = rg_template($t, $rg, TRUE /* xss */);
100 $rg['HTML:button_error'] = rg_warning($close_reopen_error, $rg);
101 $rg['rg_form_token_tag'] = 'close_reopen';
102 $rg['rg_form_token'] = rg_token_get($db, $rg, 'close_reopen');
103 $rg['HTML:close_form'] = rg_template($t, $rg, TRUE /*xss*/);
104 if (!empty($close_reopen_error))
105 $rg['HTML:button_error'] = $close_reopen_error;
106
101 107
102 108 // 'add_note' must be unconditionally included because we must insert the form // 'add_note' must be unconditionally included because we must insert the form
103 109 include($INC . "/user/repo/bug/show/add_note.php"); include($INC . "/user/repo/bug/show/add_note.php");
 
... ... include($INC . "/user/repo/bug/show/add_note.php");
106 112 $notes = rg_bug_note_list($db, $rg['ri']['repo_id'], $notes = rg_bug_note_list($db, $rg['ri']['repo_id'],
107 113 $rg['bug']['bug_id'], 0); $rg['bug']['bug_id'], 0);
108 114 if ($notes === FALSE) if ($notes === FALSE)
109 $rg['HTML:notes'] = "Cannot load notes!";
115 $rg['HTML:notes'] = rg_warning('Cannot load notes!', $rg);
110 116 else else
111 117 $rg['HTML:notes'] = rg_template_table("repo/bug/list_note", $notes, $rg); $rg['HTML:notes'] = rg_template_table("repo/bug/list_note", $notes, $rg);
112 118
119
113 120 // watch // watch
114 $watch_body = "";
121 $watch_error = '';
115 122 $watch = rg_watch_load($db, "bug", $rg['login_ui']['uid'], $rg['ri']['repo_id'], $watch = rg_watch_load($db, "bug", $rg['login_ui']['uid'], $rg['ri']['repo_id'],
116 123 $rg['bug']['bug_id']); $rg['bug']['bug_id']);
117 124 if ($watch === FALSE) { if ($watch === FALSE) {
118 $watch_body .= rg_warning("Internal error.");
125 $watch_error = rg_warning("Internal error.");
119 126 } else { } else {
120 if ($watch === 0) {
121 // user does not watch the bug, present 'watch' form
122 if (rg_var_uint("watch") == 1) {
123 // user pressed watch button
124 $r = rg_watch_add($db, "bug", $rg['login_ui']['uid'],
125 $rg['ri']['repo_id'], $rg['bug']['bug_id']);
126 if ($r === FALSE)
127 rg_internal_error("TODO: find something here");
128 $watch = 1;
127 while (1) {
128 if (rg_var_uint('watch_doit') != 1)
129 break;
130
131 if (rg_var_uint('watch') == $watch) {
132 rg_log('Already in propoer state');
133 break;
134 }
135
136 if (!rg_valid_referer()) {
137 $watch_error = rg_warning('Invalid referer; try again', $rg);
138 break;
139 }
140
141 if (!rg_token_valid($db, $rg, 'bug_watch', FALSE)) {
142 $watch_error = rg_warning('Invalid token. Try again.', $rg);
143 break;
129 144 } }
130 } else {
131 // user is already watching the bug, present 'unwatch' option
132 if (rg_var_uint("unwatch") == 1) {
133 // user pressed unwatch button
134 $r = rg_watch_del($db, "bug", $rg['login_ui']['uid'],
145
146 if (rg_var_uint('watch') == 1)
147 $r = rg_watch_add($db, 'bug', $rg['login_ui']['uid'],
148 $rg['ri']['repo_id'], $rg['bug']['bug_id']);
149 else
150 $r = rg_watch_del($db, 'bug', $rg['login_ui']['uid'],
135 151 $rg['ri']['repo_id'], $rg['bug']['bug_id']); $rg['ri']['repo_id'], $rg['bug']['bug_id']);
136 if ($r === FALSE)
137 rg_internal_error("TODO: find something here");
138 $watch = 0;
152 if ($r === FALSE) {
153 $watch_error = rg_warning('Internal error. Try again', $rg);
154 break;
139 155 } }
156
157 $watch = 1 - $watch;
158
159 break;
140 160 } }
141 161
142 if ($watch == 0)
143 $t = "repo/bug/b_watch.html";
144 else
145 $t = "repo/bug/b_unwatch.html";
146 $r = rg_template($t, $rg, TRUE /* xss */);
147 if ($r !== FALSE)
148 $watch_body .= $r;
162 $rg['rg_form_token_tag'] = 'bug_watch';
163 $rg['rg_form_token'] = rg_token_get($db, $rg, 'bug_watch');
164 $rg['bug']['watch'] = 1 - $watch;
165 $rg['HTML:watch_form'] = rg_template('repo/bug/b_watch.html',
166 $rg, TRUE /*xss*/);
149 167 } }
150 $rg['HTML:watch_form'] = $watch_body;
168 if (!empty($delete_error))
169 $rg['HTML:watch_error'] = $delete_error;
151 170
152 // delete
153 $delete_error = "";
154 while (1) {
171
172 // delete/undelete
173 $delete_error = '';
174 $del = $rg['bug']['deleted'] > 0;
175 while (rg_var_uint('del_doit') == 1) {
176 // 1 = del, 2 = undel
155 177 $del_undel = rg_var_uint("del_undel"); $del_undel = rg_var_uint("del_undel");
156 if ($del_undel == 0)
178
179 if (($del_undel == 1) && $del)
157 180 break; break;
158 181
159 $x['needed_rights'] = 'd';
160 if (rg_rights_allow($db, $x) !== TRUE) {
161 $delete_error = rg_template("repo/bug/deny_delete.html", $rg, TRUE /* xss */);
182 if (($del_undel == 2) && !$del)
162 183 break; break;
163 }
164 184
165 185 if (!rg_valid_referer()) { if (!rg_valid_referer()) {
166 186 $delete_error = rg_warning("Invalid referer; try again", $rg); $delete_error = rg_warning("Invalid referer; try again", $rg);
167 187 break; break;
168 188 } }
169 189
170 if (!rg_token_valid($db, $rg, FALSE)) {
190 if (!rg_token_valid($db, $rg, 'del_undel', FALSE)) {
171 191 $delete_error = rg_warning("Invalid token; try again.", $rg); $delete_error = rg_warning("Invalid token; try again.", $rg);
172 192 break; break;
173 193 } }
174 194
175 $ret = rg_bug_delete_undelete($db, $rg['login_ui']['uid'],
195 $x['needed_rights'] = 'd';
196 if (rg_rights_allow($db, $x) !== TRUE) {
197 $delete_error = rg_template("repo/bug/deny_delete.html",
198 $rg, TRUE /*xss*/);
199 break;
200 }
201
202 $r = rg_bug_delete_undelete($db, $rg['login_ui']['uid'],
176 203 $rg['ri']['repo_id'], $ibug['bug_id'], $del_undel); $rg['ri']['repo_id'], $ibug['bug_id'], $del_undel);
177 if ($ret === FALSE) {
204 if ($r === FALSE) {
178 205 $delete_error = rg_warning(rg_bug_error(), $rg); $delete_error = rg_warning(rg_bug_error(), $rg);
179 206 break; break;
180 207 } }
208
209 $del = 1 - $del;
181 210 break; break;
182 211 } }
183 $rg['HTML:button_error'] = $delete_error;
212 $rg['rg_form_token_tag'] = 'del_undel:' . $rg['rg_form_token'];
213 $rg['rg_form_token'] = rg_token_get($db, $rg, 'del_undel');
214 $rg['bug']['del'] = 1 - $del;
215 $rg['HTML:del_form'] = rg_template('repo/bug/b_del.html', $rg, TRUE /*xss*/);
216 if (!empty($delete_error))
217 $rg['HTML:button_error'] = $delete_error;
184 218
185 219
186 220 // We must look it up again because it can be edited above; no prob, is in cache // We must look it up again because it can be edited above; no prob, is in cache
 
... ... if ($ibug === FALSE)
189 223 rg_fatal("Cannot lookup bug!"); rg_fatal("Cannot lookup bug!");
190 224 $rg = rg_array_merge($rg, "bug", $ibug); $rg = rg_array_merge($rg, "bug", $ibug);
191 225
192 $_bug_show .= rg_template("repo/bug/show.html", $rg, TRUE /* xss */);
226 $_bug_show .= rg_template("repo/bug/show.html", $rg, TRUE /*xss*/);
193 227 ?> ?>
File inc/util.inc.php changed (mode: 100644) (index 7df267a..dd45fc0)
... ... require_once($INC . "/log.inc.php");
5 5 set_error_handler("rg_error_handler"); set_error_handler("rg_error_handler");
6 6 register_shutdown_function("rg_error_shutdown"); register_shutdown_function("rg_error_shutdown");
7 7
8 define('RG_SOCKET_NO_WAIT', 0x01);
9
8 10 $rg_util_error = ""; $rg_util_error = "";
9 11
10 12 function rg_util_set_error($str) function rg_util_set_error($str)
 
... ... function rg_template_find_true_and_false(&$s, $off, &$true_start, &$true_end,
580 582 //rg_log("DEBUG: cannot find '{{'"); //rg_log("DEBUG: cannot find '{{'");
581 583 } }
582 584
583 rg_log_exit();
585 //rg_log_exit();
584 586 return 0; return 0;
585 587 } }
586 588
 
... ... function rg_template($file, &$data, $xss_protection)
760 762 } }
761 763
762 764 $body = rg_file_get_contents($xfile); $body = rg_file_get_contents($xfile);
763 if (empty($body)) {
764 rg_log("File [$xfile] is empty. Return ''.");
765 if (empty($body))
765 766 break; break;
766 }
767 767
768 768 $ret = rg_template_string($body, 0, $data, $xss_protection); $ret = rg_template_string($body, 0, $data, $xss_protection);
769 769 break; break;
 
... ... $rg_socket_cache = array();
1295 1295 */ */
1296 1296 function rg_socket_recv_wait($socket, $wait, $timeout) function rg_socket_recv_wait($socket, $wait, $timeout)
1297 1297 { {
1298 rg_prof_start('sock_recv_wait');
1299
1298 1300 $ret = FALSE; $ret = FALSE;
1299 1301
1300 1302 if ($timeout === NULL) { if ($timeout === NULL) {
 
... ... function rg_socket_recv_wait($socket, $wait, $timeout)
1341 1343 break; break;
1342 1344 } }
1343 1345
1346 rg_prof_end('sock_recv_wait');
1344 1347 return $ret; return $ret;
1345 1348 } }
1346 1349
 
... ... function rg_socket_recv_wait($socket, $wait, $timeout)
1350 1353 */ */
1351 1354 function rg_socket_send($socket, $buf) function rg_socket_send($socket, $buf)
1352 1355 { {
1356 rg_prof_start('socket_send');
1357
1353 1358 $ret = FALSE; $ret = FALSE;
1354 1359 $len = strlen($buf); $len = strlen($buf);
1355 1360 $off = 0; $off = 0;
 
... ... function rg_socket_send($socket, $buf)
1368 1373 } }
1369 1374 } }
1370 1375
1376 rg_prof_end('socket_send');
1371 1377 return $ret; return $ret;
1372 1378 } }
1373 1379
 
... ... function rg_socket_send($socket, $buf)
1377 1383 is 0, we do not wait for an answer. If is NULL, we wait forever. is 0, we do not wait for an answer. If is NULL, we wait forever.
1378 1384 * @tries - how many time to retry if it fails * @tries - how many time to retry if it fails
1379 1385 */ */
1380 function rg_socket($path, $buf, $timeout, $tries)
1386 function rg_socket($path, $buf, $timeout, $tries, $flags)
1381 1387 { {
1382 1388 global $rg_socket_cache; global $rg_socket_cache;
1383 1389
1384 rg_prof_start("socket");
1390 rg_prof_start('socket');
1385 1391
1386 1392 $ret = FALSE; $ret = FALSE;
1387 1393 while ($tries > 0) { while ($tries > 0) {
1388 1394 if (isset($rg_socket_cache[$path])) { if (isset($rg_socket_cache[$path])) {
1389 1395 $socket = $rg_socket_cache[$path]; $socket = $rg_socket_cache[$path];
1390 1396 } else { } else {
1397 rg_prof_start('sock_create');
1391 1398 $socket = @socket_create(AF_UNIX, SOCK_STREAM, 0); $socket = @socket_create(AF_UNIX, SOCK_STREAM, 0);
1392 1399 if ($socket === FALSE) { if ($socket === FALSE) {
1393 1400 rg_log("Could not create socket (" . socket_strerror(socket_last_error()) . ")!"); rg_log("Could not create socket (" . socket_strerror(socket_last_error()) . ")!");
 
... ... function rg_socket($path, $buf, $timeout, $tries)
1395 1402 } }
1396 1403
1397 1404 while ($tries > 0) { while ($tries > 0) {
1405 rg_prof_start('sock_conn');
1398 1406 $r = @socket_connect($socket, $path); $r = @socket_connect($socket, $path);
1407 rg_prof_end('sock_conn');
1399 1408 if ($r === FALSE) { if ($r === FALSE) {
1400 1409 $tries--; $tries--;
1401 1410 usleep(50 * 1000); usleep(50 * 1000);
 
... ... function rg_socket($path, $buf, $timeout, $tries)
1408 1417 rg_log("Could not connect the socket (" . socket_strerror(socket_last_error()) . ")!"); rg_log("Could not connect the socket (" . socket_strerror(socket_last_error()) . ")!");
1409 1418 break; break;
1410 1419 } }
1420 rg_prof_end('sock_create');
1411 1421
1412 1422 $rg_socket_cache[$path] = $socket; $rg_socket_cache[$path] = $socket;
1413 1423 } }
 
... ... function rg_socket($path, $buf, $timeout, $tries)
1419 1429 continue; continue;
1420 1430 } }
1421 1431
1422 if ($timeout === 0) {
1423 rg_log("We do not have to wait. Exit.");
1424 $ret = "";
1432 if ($flags & RG_SOCKET_NO_WAIT) {
1433 //rg_log('We do not have to wait. Exit.');
1434 $ret = '';
1425 1435 break; break;
1426 1436 } }
1427 1437
File root/index.php changed (mode: 100644) (index e5dc14c..778dd1c)
... ... $rg['rg_account_allow_creation'] = $rg_account_allow_creation;
43 43
44 44 // Init variables // Init variables
45 45 $THEME_URL = "/themes/" . $rg_theme; $THEME_URL = "/themes/" . $rg_theme;
46 $rg['rg_redirect_html'] = 0;
46 47 $rg['rg_theme_url'] = $THEME_URL; $rg['rg_theme_url'] = $THEME_URL;
47 48 $rg['login_ui'] = array(); $rg['login_ui'] = array();
48 49 $rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0); $rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0);
 
... ... $rg['ri'] = array("repo_id" => 0, "uid" => 0);
50 51 $rg['bug'] = array("bug_id" => 0); $rg['bug'] = array("bug_id" => 0);
51 52 $rg['HTML:submenu1'] = ""; $rg['HTML:submenu1'] = "";
52 53 $rg['HTML:submenu2'] = ""; $rg['HTML:submenu2'] = "";
54 $rg['debug'] = rg_var_uint('rg_debug');
53 55
54 56 // We have variable 'vv' passed from webserver - build 'op' and rest of paras // We have variable 'vv' passed from webserver - build 'op' and rest of paras
55 57 $sparas = rg_var_str("vv"); $sparas = rg_var_str("vv");
 
... ... if ($r === FALSE) {
146 148
147 149 if ($rg['login_ui']['uid'] > 0) { if ($rg['login_ui']['uid'] > 0) {
148 150 $rg['login_ui']['homepage'] = rg_re_userpage($rg['login_ui']); $rg['login_ui']['homepage'] = rg_re_userpage($rg['login_ui']);
149 $rg['logout_token'] = rg_token_get($db, $rg);
151 $rg['logout_token'] = rg_token_get($db, $rg, 'logout');
150 152 } else { } else {
151 153 $rg['login_ui']['username'] = ""; $rg['login_ui']['username'] = "";
152 154 $rg['login_ui']['homepage'] = ""; $rg['login_ui']['homepage'] = "";
 
... ... header('Cache-Control: private, no-cache');
161 163
162 164 // Caching // Caching
163 165 $proto = rg_var_str('SERVER_PROTOCOL'); $proto = rg_var_str('SERVER_PROTOCOL');
164 rg_log('DEBUG: proto=' . $proto);
165 166 if (strcmp($proto, 'HTTP/1.1') == 0) { if (strcmp($proto, 'HTTP/1.1') == 0) {
166 167 $we_have = sha1($_c); $we_have = sha1($_c);
167 168 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) if (isset($_SERVER['HTTP_IF_NONE_MATCH']))
 
... ... if (strcmp($proto, 'HTTP/1.1') == 0) {
172 173 if (strcmp($client_have, $we_have) == 0) { if (strcmp($client_have, $we_have) == 0) {
173 174 rg_log('CACHE: Client has the right version'); rg_log('CACHE: Client has the right version');
174 175 header('HTTP/1.1 304 Not modified'); header('HTTP/1.1 304 Not modified');
175 header('ETag: ' . $we_have);
176 176 } else { } else {
177 rg_log('CACHE: Client has NOT the right version [' . $client_have . ']');
178 177 header('ETag: ' . $we_have); header('ETag: ' . $we_have);
179 178 echo $_c; echo $_c;
180 179 } }
181 180 } else { } else {
181 rg_log('WARN: Un-handled protocol ' . $proto);
182 182 echo $_c; echo $_c;
183 183 } }
184 184
File root/themes/default/download-vm.html changed (mode: 100644) (index e36f928..63bb4c5)
275 275
276 276 You must check the following list because you may want to:<br /> You must check the following list because you may want to:<br />
277 277 * generate new SSL/TLS keys<br /> * generate new SSL/TLS keys<br />
278 * Add the vm in the update plan (periodic 'yum update')<br />
279 * edit /etc/sysconfig/clock to set the timezone (needs a restart of
280 some services or reboot)<br />
278 * add the vm in the update plan (periodic 'yum update')<br />
279 * run timedatectl set-timezone 'Continent/City' to set the timezone
280 (needs a restart of some services or reboot)<br />
281 281 * change root password: run 'passwd' (initial password is 'aaaa')<br /> * change root password: run 'passwd' (initial password is 'aaaa')<br />
282 282 * allow this virtual machine to send mail (add it to the relay allow list)<br /> * allow this virtual machine to send mail (add it to the relay allow list)<br />
283 283 * set a static IP address instead of DHCP<br /> * set a static IP address instead of DHCP<br />
File root/themes/default/features.html changed (mode: 100644) (index cdf14eb..594ff8c)
45 45 <div class="island_cell"> <div class="island_cell">
46 46 <div class="island"> <div class="island">
47 47 <div class="island_title">Very easy to maintain</div> <div class="island_title">Very easy to maintain</div>
48 RocketGit has very little dependencies, all packed
49 in the main-stream distributions. You just upgrade your
48 RocketGit has very few dependencies, all packed
49 in the main-stream distributions, therefore you just upgrade your
50 50 operating system and RocketGit will be up-to-date too. operating system and RocketGit will be up-to-date too.
51 51 </div> </div>
52 52 </div> </div>
File root/themes/default/repo/bug/b_close.html changed (mode: 100644) (index c57de52..e96303d)
2 2 <input type="hidden" name="close_reopen" value="1" /> <input type="hidden" name="close_reopen" value="1" />
3 3 <input type="hidden" name="state" value="2" /> <input type="hidden" name="state" value="2" />
4 4 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
5
6 5 <input type="submit" name="button" value="Close" /> <input type="submit" name="button" value="Close" />
7 6 </form> </form>
File root/themes/default/repo/bug/b_del.html added (mode: 100644) (index 0000000..c29cdae)
1 <form method="post" action="@@bug::url@@">
2 <input type="hidden" name="del_doit" value="1" />
3 <input type="hidden" name="del_undel" value="@@bug::del@@" />
4 <input type="hidden" name="token" value="@@rg_form_token@@" />
5 <input type="submit" name="button" value="@@if(@@bug::del@@ == 1){{Delete}}{{Undelete}}" />
6 </form>
File root/themes/default/repo/bug/b_edit.html changed (mode: 100644) (index 1fb238d..a51b0a8)
1 1 <form method="post" action="@@bug::url@@"> <form method="post" action="@@bug::url@@">
2 2 <input type="hidden" name="edit" value="1" /> <input type="hidden" name="edit" value="1" />
3 3 <!-- no need for token --> <!-- no need for token -->
4
5 4 <input type="submit" name="button" value="Edit" /> <input type="submit" name="button" value="Edit" />
6 5 </form> </form>
File root/themes/default/repo/bug/b_reopen.html changed (mode: 100644) (index a0645e9..6b93643)
2 2 <input type="hidden" name="close_reopen" value="1" /> <input type="hidden" name="close_reopen" value="1" />
3 3 <input type="hidden" name="state" value="1" /> <input type="hidden" name="state" value="1" />
4 4 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
5
6 5 <input type="submit" name="button" value="Re-open" /> <input type="submit" name="button" value="Re-open" />
7 6 </form> </form>
File root/themes/default/repo/bug/b_unwatch.html deleted (index 1ba3d8d..0000000)
1 <form method="post" action="@@bug::url@@">
2 <input type="hidden" name="unwatch" value="1" />
3 <input type="hidden" name="token" value="@@rg_form_token@@" />
4
5 <input type="submit" name="button" value="Unwatch" />
6 </form>
File root/themes/default/repo/bug/b_watch.html changed (mode: 100644) (index f6a97fa..94a95ee)
1 1 <form method="post" action="@@bug::url@@"> <form method="post" action="@@bug::url@@">
2 <input type="hidden" name="watch" value="1" />
2 <input type="hidden" name="watch_doit" value="1" />
3 <input type="hidden" name="watch" value="@@bug::watch@@" />
3 4 <input type="hidden" name="token" value="@@rg_form_token@@" /> <input type="hidden" name="token" value="@@rg_form_token@@" />
4
5 <input type="submit" name="button" value="Watch" />
5 <input type="submit" name="button" value="@@if(@@bug::watch@@ == 1){{Watch}}{{Unwatch}}" />
6 6 </form> </form>
File root/themes/default/repo/bug/show.html changed (mode: 100644) (index 812ae71..0cce16f)
7 7 <td>@@edit_form@@</td> <td>@@edit_form@@</td>
8 8 <td>@@watch_form@@</td> <td>@@watch_form@@</td>
9 9 <td>@@close_form@@</td> <td>@@close_form@@</td>
10 <td>
11 <form method="post" action="@@bug::url@@">
12 <input type="hidden" name="del_undel" value="@@if(@@bug::deleted@@ == 0){{1}}{{2}}" />
13 <input type="hidden" name="token" value="@@rg_form_token@@" />
14 <input type="submit" name="button" value="@@if(@@bug::deleted@@ == 0){{Delete}}{{Undelete}}" />
15 </form>
16 </td>
10 <td>@@del_form@@</td>
17 11 </tr> </tr>
18 12 </tbody> </tbody>
19 13 </table> </table>
File scripts/cache.php changed (mode: 100644) (index 6f2a78c..c3f4837)
... ... function rg_handle_command($k, &$conn_table, $cmd)
47 47
48 48 $s = &$conn_table['conns'][$k]; $s = &$conn_table['conns'][$k];
49 49
50 $a = explode(" ", $cmd, 2);
50 $a = explode(" ", $cmd, 3);
51 51 $buf = "ER Invalid command\n"; $buf = "ER Invalid command\n";
52 52 while (1) { while (1) {
53 if (!isset($a[0]))
53 // We must have at least 2 parameters: cmd and flags
54 if (!isset($a[1]))
54 55 break; break;
55 56
56 57 $cmd = trim($a[0]); $cmd = trim($a[0]);
58 $flags = trim($a[1]);
59 if (strncmp($flags, 'F=', 2) != 0) {
60 rg_log('Invalid command (no flags): $cmd');
61 break;
62 }
63 $flags = substr($flags, 2);
64 $no_wait = FALSE;
65 if (strstr($flags, 'W'))
66 $no_wait = TRUE;
57 67
58 /* here, no parameters */
68 /* From here, commands with no parameters */
59 69
60 /* From, here, at least 1 para */
61 if (!isset($a[1]))
70 /* From here, at least 1 para */
71 if (!isset($a[2]))
62 72 break; break;
63 $para1 = trim($a[1]);
73 $para1 = trim($a[2]);
64 74
65 75 if (strcmp($cmd, "SET") == 0) { if (strcmp($cmd, "SET") == 0) {
66 76 $ns_var_value = explode("=", $para1, 2); $ns_var_value = explode("=", $para1, 2);
 
... ... function rg_handle_command($k, &$conn_table, $cmd)
159 169 break; break;
160 170 } }
161 171
162 $s['send'] .= $buf;
163 $conn_table['w'][$k] = $s['socket'];
172 if ($no_wait === FALSE) {
173 $s['send'] .= $buf;
174 $conn_table['w'][$k] = $s['socket'];
175 }
164 176 } }
165 177
166 178 function rg_handle_recv($k, &$conn_table) function rg_handle_recv($k, &$conn_table)
File tests/Makefile changed (mode: 100644) (index 81979eb..de781a3)
1 1 tests := git_log1.sh \ tests := git_log1.sh \
2 2 http_admin http_bug \ http_admin http_bug \
3 token util log state cache prof db event rights keys user repo git bug \
4 hook_update http_create_account http_login http_settings http_csrf \
5 http_top git2
3 http_create_account http_login http_settings http_csrf http_top \
4 token util log state cache prof db event rights keys user repo git \
5 bug hook_update git2
6 6 .PHONY: $(tests) .PHONY: $(tests)
7 7
8 8 all: $(tests) all: $(tests)
9 9 @echo "All OK. Good work!" @echo "All OK. Good work!"
10 @ls -l err-*
10 @-ls -l err-*
11 @echo "Do not forget to check for errors in /var/log/rocketgit!"
11 12
12 13 git_log1.sh: git_log1.sh:
13 14 ./git_log1.sh ./git_log1.sh
File tests/git2.php changed (mode: 100644) (index ef2234a..cb017a7)
... ... if ($r === FALSE) {
73 73 rg_log("Cannot load form!"); rg_log("Cannot load form!");
74 74 exit(1); exit(1);
75 75 } }
76 if (empty($r['token'])) {
76 if (empty($r['tokens']['keys'])) {
77 77 rg_log_ml("token not found! r:" . print_r($r, TRUE)); rg_log_ml("token not found! r:" . print_r($r, TRUE));
78 78 exit(1); exit(1);
79 79 } }
80 80
81 81 rg_log("Uploading the key..."); rg_log("Uploading the key...");
82 82 $key = file_get_contents("git2key.pub"); $key = file_get_contents("git2key.pub");
83 $data = array('add' => 1, 'token' => $r['token'], 'key' => $key);
83 $data = array('add' => 1, 'token' => $r['tokens']['keys'], 'key' => $key);
84 84 $headers = array('Cookie: sid=' . $good_sid); $headers = array('Cookie: sid=' . $good_sid);
85 85 $r = do_req($test_url . '/op/settings/keys?t=git2', $data, $headers); $r = do_req($test_url . '/op/settings/keys?t=git2', $data, $headers);
86 86 if ($r === FALSE) { if ($r === FALSE) {
File tests/helpers.inc.php changed (mode: 100644) (index d61fc17..1773bb5)
... ... function rg_test_create_user($db, &$rg_ui)
41 41 } }
42 42 rg_sql_free_result($res); rg_sql_free_result($res);
43 43
44 rg_cache_unset('username_to_uid::' . $username);
44 rg_cache_unset('username_to_uid::' . $username, RG_SOCKET_NO_WAIT);
45 45
46 46 $rg_ui = array_merge($new, $rg_ui); $rg_ui = array_merge($new, $rg_ui);
47 47 $r = rg_user_edit($db, $rg_ui); $r = rg_user_edit($db, $rg_ui);
 
... ... function rg_test_create_repo($db, $rg_ui, &$extra)
138 138 $res = rg_sql_query($db, $sql); $res = rg_sql_query($db, $sql);
139 139 rg_sql_free_result($res); rg_sql_free_result($res);
140 140 $new['repo_id'] = $repo_id; $new['repo_id'] = $repo_id;
141 rg_cache_unset('repo_by_name::' . $rg_ui['uid']);
141 rg_cache_unset('repo_by_name::' . $rg_ui['uid'],
142 RG_SOCKET_NO_WAIT);
142 143 } }
143 144
144 145 return TRUE; return TRUE;
File tests/http.inc.php changed (mode: 100644) (index 5db8725..fcc73ba)
... ... function do_req($url, &$data, &$headers)
21 21 rg_log_ml("do_req url[$url] data=" . print_r($data, TRUE) rg_log_ml("do_req url[$url] data=" . print_r($data, TRUE)
22 22 . "headers=" . print_r($headers, TRUE)); . "headers=" . print_r($headers, TRUE));
23 23
24 if (!strstr($url, '?'))
25 $url .= '?rg_debug=1';
26 else
27 $url .= '&rg_debug=1';
28 rg_log('DEBUG: url=' . $url);
29
24 30 $c = curl_init($url); $c = curl_init($url);
25 31 if (count($data) > 0) { if (count($data) > 0) {
26 32 curl_setopt($c, CURLOPT_POST, 1); curl_setopt($c, CURLOPT_POST, 1);
 
... ... function do_req($url, &$data, &$headers)
76 82 } }
77 83
78 84 // Check for XSS // Check for XSS
79 if (strstr($ret['body'], '<xss>')) {
85 if (stristr($ret['body'], '<xss>')) {
80 86 file_put_contents('http_xss.out', $ret['body']); file_put_contents('http_xss.out', $ret['body']);
81 87 rg_log("Found <xss> token! Check http_xss.out. Not good!"); rg_log("Found <xss> token! Check http_xss.out. Not good!");
82 88 exit(1); exit(1);
83 89 } }
84 90
85 // find token
86 $x = preg_match('/ name="token" value="([a-zA-Z0-9]*)"/', $ret['body'], $matches);
91 $ret['tokens'] = array();
92 $x = preg_match_all('/ name="token" value="([a-zA-Z0-9_:]*)"/', $ret['body'], $matches);
93 //rg_log_ml('DEBUG: matches: ' . print_r($matches, TRUE));
87 94 if (($x === FALSE) || (!isset($matches[1]))) { if (($x === FALSE) || (!isset($matches[1]))) {
88 95 //rg_log("CHECK: no token found"); //rg_log("CHECK: no token found");
89 $ret['token'] = "";
90 96 } else { } else {
91 $ret['token'] = $matches[1];
97 foreach ($matches[1] as $m) {
98 $t = explode(':', $m);
99 if (!isset($t[1])) {
100 rg_log('Invalid debug token: ' . $m);
101 exit(1);
102 }
103 $ret['tokens'][$t[1]] = $t[0];
104 }
92 105 } }
106 rg_log_ml('DEBUG ret[tokens]: ' . print_r($ret['tokens'], TRUE));
93 107
94 108 // find logout token // find logout token
95 $x = preg_match('/logout\?token=([a-zA-Z0-9]*)"/', $ret['body'], $matches);
109 $x = preg_match('/logout\?token=([a-zA-Z0-9:]*)"/', $ret['body'], $matches);
110 //rg_log_ml('DEBUG: matches[logout]: ' . print_r($matches, TRUE));
96 111 if (($x === FALSE) || (!isset($matches[1]))) { if (($x === FALSE) || (!isset($matches[1]))) {
97 $ret['logout_token'] = "";
112 $ret['tokens']['logout'] = '';
98 113 } else { } else {
99 $ret['logout_token'] = $matches[1];
114 $t = explode(':', $matches[1]);
115 $ret['tokens']['logout'] = $t[0];
100 116 } }
101 117
102 118 $x = preg_match('/Location: (.*)\s/', $ret['header'], $matches); $x = preg_match('/Location: (.*)\s/', $ret['header'], $matches);
 
... ... function do_req($url, &$data, &$headers)
116 132 return $f; return $f;
117 133 } }
118 134
135 @rename('http-last.out', 'http-prev.out');
136 file_put_contents('http-last.out', $ret['body']);
137
119 138 return $ret; return $ret;
120 139 } }
121 140
 
... ... function test_login($url, $rg_ui, &$good_sid)
136 155 return FALSE; return FALSE;
137 156 } }
138 157 $good_sid = $r['sid']; $good_sid = $r['sid'];
139 $good_token = $r['token'];
158 $good_token = $r['tokens']['login'];
140 159 rg_log("good: sid=$good_sid token=$good_token"); rg_log("good: sid=$good_sid token=$good_token");
141 160 if (strncmp($good_sid, "X", 1) != 0) { if (strncmp($good_sid, "X", 1) != 0) {
142 161 rg_log("Seems we did not get a pre-login session!"); rg_log("Seems we did not get a pre-login session!");
 
... ... function test_restore($db)
188 207 } }
189 208 rg_sql_free_result($res); rg_sql_free_result($res);
190 209
191 rg_cache_unset("user::4");
210 rg_cache_unset('user::4', RG_SOCKET_NO_WAIT);
192 211 } }
193 212
194 213 /* /*
File tests/http_admin.php changed (mode: 100644) (index a097976..789ce9a)
... ... if ($r === FALSE) {
31 31 exit(1); exit(1);
32 32 } }
33 33 $good_sid = $r['sid']; $good_sid = $r['sid'];
34 $good_token = $r['token'];
34 $good_token = $r['tokens']['login'];
35 35
36 36
37 37 rg_log("Do the login (sid=$good_sid token=$good_token)..."); rg_log("Do the login (sid=$good_sid token=$good_token)...");
 
... ... if ($r === FALSE) {
60 60 rg_log("Cannot load add bug form."); rg_log("Cannot load add bug form.");
61 61 exit(1); exit(1);
62 62 } }
63 $token = $r['token'];
63 if (!isset($r['tokens']['admin_invites_hl'])) {
64 rg_log("No admin_invites_hl token!");
65 exit(1);
66 }
67 $token = $r['tokens']['admin_invites_hl'];
64 68
65 69 rg_log("Posting invites form (token=$token)..."); rg_log("Posting invites form (token=$token)...");
66 70 $data = array('doit' => 1, 'token' => $token, $data = array('doit' => 1, 'token' => $token,
 
... ... if ($row['state'] != 1) {
81 85 */ */
82 86
83 87 rg_prof_log(); rg_prof_log();
84 rg_log("Done!");
88 rg_log("OK!");
85 89 ?> ?>
File tests/http_bug.php changed (mode: 100644) (index 9802330..fc08ebc)
... ... if ($r === FALSE)
27 27 exit(1); exit(1);
28 28
29 29
30 rg_log("Loading bug form...");
30 rg_log('');
31 rg_log_enter("Loading bug form...");
31 32 $url = "/user/" . $u1['username'] . "/" . $repo['name'] . "/bug/add"; $url = "/user/" . $u1['username'] . "/" . $repo['name'] . "/bug/add";
32 33 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
33 34 $data = array(); $data = array();
 
... ... if ($r === FALSE) {
36 37 rg_log('Cannot load add bug form.'); rg_log('Cannot load add bug form.');
37 38 exit(1); exit(1);
38 39 } }
39 $token = $r['token'];
40 $token = $r['tokens']['bug_edit_hl'];
40 41 if (empty($token)) { if (empty($token)) {
41 rg_log_ml(print_r($r, TRUE));
42 42 rg_log("Seems I cannot load a token. See above."); rg_log("Seems I cannot load a token. See above.");
43 43 exit(1); exit(1);
44 44 } }
45 rg_log_exit();
45 46
46 rg_log("Posting bug form (token=$token)...");
47 rg_log('');
48 rg_log_enter("Posting bug form (token=$token)...");
47 49 $labels = array('a/b', 'uu::bb', '<xss>'); sort($labels); $labels = array('a/b', 'uu::bb', '<xss>'); sort($labels);
48 50 $data = array('doit' => 1, 'edit' => 1, 'token' => $token, $data = array('doit' => 1, 'edit' => 1, 'token' => $token,
49 51 'title' => 'Title1 space<xss>', 'title' => 'Title1 space<xss>',
 
... ... if (strcmp($p1, $p2) != 0) {
89 91 rg_log('Labels are different [' . $p1 . '] != [' . $p2 . ']!'); rg_log('Labels are different [' . $p1 . '] != [' . $p2 . ']!');
90 92 exit(1); exit(1);
91 93 } }
94 rg_log_exit();
92 95
93 96
94 rg_log("Testing adding a note");
97 rg_log('');
98 rg_log_enter("Testing adding a note");
95 99
96 rg_log("Loading bug/note form...");
100 rg_log_enter("Loading bug/note form...");
97 101 $url = "/user/" . $u1['username'] . "/" . $repo['name'] . "/bug/1"; $url = "/user/" . $u1['username'] . "/" . $repo['name'] . "/bug/1";
98 102 $data = array('_test' => 'adding a note'); $data = array('_test' => 'adding a note');
99 103 $r = do_req($test_url . $url, $data, $headers); $r = do_req($test_url . $url, $data, $headers);
 
... ... if ($r === FALSE) {
101 105 rg_log("Cannot load bug page."); rg_log("Cannot load bug page.");
102 106 exit(1); exit(1);
103 107 } }
104 $token = $r['token'];
108 if (!isset($r['tokens']['note_add'])) {
109 rg_log('note_add token not present!');
110 exit(1);
111 }
112 $token = $r['tokens']['note_add'];
113 rg_log_exit();
105 114
106 rg_log("Posting note add form (token=$token)...");
115 rg_log_enter("Posting note add form (token=$token)...");
107 116 $note = 'This is a note<xss>'; $note = 'This is a note<xss>';
108 117 $data = array('note_add_doit' => 1, 'token' => $token, $data = array('note_add_doit' => 1, 'token' => $token,
109 118 'note' => $note, 'note' => $note,
 
... ... if ($row['uid'] != $u1['uid']) {
126 135 rg_log('uid is not ok [' . $row['uid'] . '] != [' . $u1['uid'] . ']!'); rg_log('uid is not ok [' . $row['uid'] . '] != [' . $u1['uid'] . ']!');
127 136 exit(1); exit(1);
128 137 } }
138 rg_log_exit();
129 139
140 rg_log_exit();
130 141
131 // Test closing a bug
132 $token = $r['token'];
133 rg_log("Posting close bug form...");
142
143 $token = $r['tokens']['close_reopen'];
144 rg_log('');
145 rg_log_enter("Posting close bug form (token=$token)...");
134 146 $data = array('token' => $token, $data = array('token' => $token,
135 147 'close_reopen' => 1, 'close_reopen' => 1,
136 148 'state' => 2, 'state' => 2,
 
... ... $res = rg_sql_query($db, $sql);
146 158 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
147 159 rg_sql_free_result($res); rg_sql_free_result($res);
148 160 if ($row['state'] != 2) { if ($row['state'] != 2) {
149 rg_log('Seems we could not close the bug; state= [' . $row['state']);
161 rg_log('Seems we could not close the bug; state=[' . $row['state'] . ']');
150 162 exit(1); exit(1);
151 163 } }
164 rg_log_exit();
152 165
153
154 // Test re-opening a bug
155 $token = $r['token'];
156 rg_log("Posting re-open bug form...");
166 $token = $r['tokens']['close_reopen'];
167 rg_log('');
168 rg_log_enter("Posting re-open bug form (token=$token)...");
157 169 $data = array('token' => $token, $data = array('token' => $token,
158 170 'close_reopen' => 1, 'close_reopen' => 1,
159 171 'state'=> 1, 'state'=> 1,
160 172 '_test' => 're-opn bug'); '_test' => 're-opn bug');
161 173 $r = do_req($test_url . $url, $data, $headers); $r = do_req($test_url . $url, $data, $headers);
162 174 if ($r === FALSE) { if ($r === FALSE) {
163 rg_log('Cannot post bug request.');
175 rg_log('Cannot post bug request (check http_bug.out for last answer).');
164 176 exit(1); exit(1);
165 177 } }
166 178 $sql = 'SELECT * FROM bugs WHERE repo_id = ' . $repo['repo_id'] $sql = 'SELECT * FROM bugs WHERE repo_id = ' . $repo['repo_id']
 
... ... $row = rg_sql_fetch_array($res);
170 182 rg_sql_free_result($res); rg_sql_free_result($res);
171 183 if ($row['state'] != 1) { if ($row['state'] != 1) {
172 184 rg_log('Seems we could not re-open the bug;' rg_log('Seems we could not re-open the bug;'
173 . ' state= [' . $row['state'] . ']!');
185 . ' state=[' . $row['state'] . ']!');
174 186 exit(1); exit(1);
175 187 } }
188 rg_log_exit();
176 189
177
178 rg_log("Testing deleting a bug");
190 rg_log('');
191 rg_log_enter("Testing deleting a bug");
179 192 for ($i = 0; $i <= 1; $i++) { for ($i = 0; $i <= 1; $i++) {
180 $token = $r['token'];
181 rg_log("Posting delete bug form...");
193 $token = $r['tokens']['del_undel'];
194 rg_log("Posting delete bug form (token=$token)...");
182 195 $data = array('token' => $token, $data = array('token' => $token,
196 'del_doit' => 1,
183 197 'del_undel' => $i + 1, 'del_undel' => $i + 1,
184 '_test' => 'deleting a bug');
198 '_test' => 'deleting a bug (i=' . $i . ')');
185 199 $r = do_req($test_url . $url, $data, $headers); $r = do_req($test_url . $url, $data, $headers);
186 200 if ($r === FALSE) { if ($r === FALSE) {
187 201 rg_log('Cannot post bug request.'); rg_log('Cannot post bug request.');
 
... ... for ($i = 0; $i <= 1; $i++) {
198 212 $test = $row['deleted'] == 0; $test = $row['deleted'] == 0;
199 213 if (!$test) { if (!$test) {
200 214 rg_log('i=' . $i . ': Seems we could not delete/undelete the bug;' rg_log('i=' . $i . ': Seems we could not delete/undelete the bug;'
201 . ' deleted= [' . $row['deleted'] . ']!');
215 . ' deleted=[' . $row['deleted'] . ']!');
202 216 exit(1); exit(1);
203 217 } }
204 218 if ($row['deleted_who'] != $u1['uid']) { if ($row['deleted_who'] != $u1['uid']) {
205 219 rg_log('i=' . $i . ': Seems the deleted_who was not updated;' rg_log('i=' . $i . ': Seems the deleted_who was not updated;'
206 . ' deleted_who= [' . $row['deleted_who'] . ']!');
220 . ' deleted_who=[' . $row['deleted_who'] . ']!');
207 221 exit(1); exit(1);
208 222 } }
209 223 } }
224 rg_log_exit();
210 225
211 226
212 // Test watching a bug - we need to login as a different user
227 rg_log('');
228 rg_log_enter("Test watching a bug - we need to login as a different user");
213 229 $r = test_login($test_url, $u2, $good_sid); $r = test_login($test_url, $u2, $good_sid);
214 230 if ($r === FALSE) if ($r === FALSE)
215 231 exit(1); exit(1);
 
... ... for ($i = 0; $i <= 1; $i++) {
224 240 rg_log('Cannot load bug form.'); rg_log('Cannot load bug form.');
225 241 exit(1); exit(1);
226 242 } }
227 $token = $r['token'];
243 $token = $r['tokens']['bug_watch'];
228 244
229 245 rg_log("Posting (un)watch bug form..."); rg_log("Posting (un)watch bug form...");
230 $data = array('token' => $token, 'watch' => $i, 'unwatch' => 1 - $i,
246 $data = array('token' => $token, 'watch_doit' => 1, 'watch' => $i,
231 247 '_test' => 'post-watch-' . $i); '_test' => 'post-watch-' . $i);
232 248 $r = do_req($test_url . $url, $data, $headers); $r = do_req($test_url . $url, $data, $headers);
233 249 if ($r === FALSE) { if ($r === FALSE) {
 
... ... for ($i = 0; $i <= 1; $i++) {
261 277 } }
262 278 } }
263 279 } }
264
280 rg_log_exit();
265 281
266 282 rg_prof_log(); rg_prof_log();
267 283 rg_log("OK!"); rg_log("OK!");
File tests/http_create_account.php changed (mode: 100644) (index 34397c7..d08c2c4)
... ... if ($r === FALSE) {
22 22 exit(1); exit(1);
23 23 } }
24 24 $good_sid = $r['sid']; $good_sid = $r['sid'];
25 $good_token = $r['token'];
25 $good_token = $r['tokens']['user_edit_hl'];
26 26
27 27 $uniq = time(); $uniq = time();
28 28
File tests/http_csrf.php changed (mode: 100644) (index 1467ad1..ea73956)
... ... $rg_cache_enable = TRUE;
22 22
23 23 $now = time(); $now = time();
24 24
25 test_set_ua("user-agent-1");
25 26 rg_test_create_user($db, $rg_ui); rg_test_create_user($db, $rg_ui);
26 27 $r = test_login($test_url, $rg_ui, $good_sid); $r = test_login($test_url, $rg_ui, $good_sid);
27 28 if ($r === FALSE) { if ($r === FALSE) {
 
... ... if ($r === FALSE) {
29 30 exit(1); exit(1);
30 31 } }
31 32
32 rg_log("Loading suggestion form (ua test)");
33 rg_log_enter("Loading suggestion form (ua test)");
33 34 test_set_ua("user-agent-1"); test_set_ua("user-agent-1");
34 35 test_set_referer($test_url); test_set_referer($test_url);
35 36 $data = array(); $data = array();
36 37 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
37 38 $r = do_req($test_url . "/op/suggestion?t=load_suggestion_form_ua", $data, $headers); $r = do_req($test_url . "/op/suggestion?t=load_suggestion_form_ua", $data, $headers);
38 39 if (!stristr($r['body'], "action=\"/op/suggestion\"")) { if (!stristr($r['body'], "action=\"/op/suggestion\"")) {
39 rg_log_ml(print_r($r, TRUE));
40 40 rg_log("Cannot load form! See above."); rg_log("Cannot load form! See above.");
41 41 exit(1); exit(1);
42 42 } }
43 $good_token = $r['token'];
43 $good_token = $r['tokens']['suggestion'];
44 rg_log_exit();
44 45
45 rg_log("Try posting with different user-agent: should not work");
46 rg_log_enter("Try posting with different user-agent: should not work");
46 47 test_set_ua("user-agent-2"); test_set_ua("user-agent-2");
47 48 $data = array( $data = array(
48 49 "doit" => 1, "doit" => 1,
 
... ... $data = array(
52 53 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
53 54 $r = do_req($test_url . "/op/suggestion?t=post_suggestion_form_diff_ua", $data, $headers); $r = do_req($test_url . "/op/suggestion?t=post_suggestion_form_diff_ua", $data, $headers);
54 55 if (!stristr($r['body'], "invalid token")) { if (!stristr($r['body'], "invalid token")) {
55 rg_log_ml(print_r($r, TRUE));
56 56 rg_log("Seems I could add a suggestion bypassing CSRF" rg_log("Seems I could add a suggestion bypassing CSRF"
57 57 . " protection based on user-agent! See above."); . " protection based on user-agent! See above.");
58 58 exit(1); exit(1);
59 59 } }
60 rg_log_exit();
60 61
61 62
62 rg_log("Loading suggestion form (referer test)");
63 rg_log_enter("Loading suggestion form (referer test)");
63 64 test_set_ua("user-agent-1"); test_set_ua("user-agent-1");
64 65 test_set_referer($test_url); test_set_referer($test_url);
65 66 $data = array(); $data = array();
66 67 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
67 68 $r = do_req($test_url . "/op/suggestion?t=load_suggestion_form_referer", $data, $headers); $r = do_req($test_url . "/op/suggestion?t=load_suggestion_form_referer", $data, $headers);
68 69 if (!stristr($r['body'], "action=\"/op/suggestion\"")) { if (!stristr($r['body'], "action=\"/op/suggestion\"")) {
69 rg_log_ml(print_r($r, TRUE));
70 70 rg_log("Cannot load form! See above."); rg_log("Cannot load form! See above.");
71 71 exit(1); exit(1);
72 72 } }
73 $good_token = $r['token'];
74 $good_logout_token = $r['logout_token'];
73 $good_token = $r['tokens']['suggestion'];
74 $good_logout_token = $r['tokens']['logout'];
75 rg_log_exit();
75 76
76 rg_log("Try posting with different referer: should not work");
77 rg_log_enter("Try posting with different referer: should not work");
77 78 test_set_ua("user-agent-1"); test_set_ua("user-agent-1");
78 79 test_set_referer("http://attacker.com:4000/bla"); test_set_referer("http://attacker.com:4000/bla");
79 80 $data = array( $data = array(
 
... ... $data = array(
84 85 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
85 86 $r = do_req($test_url . "/op/suggestion?t=post_suggestion_form_diff_referer", $data, $headers); $r = do_req($test_url . "/op/suggestion?t=post_suggestion_form_diff_referer", $data, $headers);
86 87 if (!stristr($r['body'], "invalid referer")) { if (!stristr($r['body'], "invalid referer")) {
87 rg_log_ml(print_r($r, TRUE));
88 88 rg_log_ml("Seems I could add a suggestion bypassing CSRF" rg_log_ml("Seems I could add a suggestion bypassing CSRF"
89 89 . " protection based on referer! See above."); . " protection based on referer! See above.");
90 90 exit(1); exit(1);
91 91 } }
92 rg_log_exit();
92 93
93 94
94 rg_log("Testing logout CSRF (wrong token)...");
95 rg_log_enter("Testing logout CSRF (wrong token)...");
95 96 test_set_ua("user-agent-1"); test_set_ua("user-agent-1");
96 97 test_set_referer($test_url); test_set_referer($test_url);
97 98 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
98 99 $data['token'] = strtoupper($good_token); $data['token'] = strtoupper($good_token);
99 100 $r = do_req($test_url . "/op/logout?t=wrong_token", $data, $headers); $r = do_req($test_url . "/op/logout?t=wrong_token", $data, $headers);
100 101 if (stristr($r['body'], "You are now logged out")) { if (stristr($r['body'], "You are now logged out")) {
101 rg_log_ml(print_r($r, TRUE));
102 102 rg_log("No error on logout with wrong token?! See above."); rg_log("No error on logout with wrong token?! See above.");
103 103 exit(1); exit(1);
104 104 } }
105 rg_log_exit();
105 106
106 107
107 rg_log("Testing logout CSRF (token passed in cookie)...");
108 rg_log_enter("Testing logout CSRF (token passed in cookie)...");
108 109 test_set_ua("user-agent-1"); test_set_ua("user-agent-1");
109 110 test_set_referer($test_url); test_set_referer($test_url);
110 111 $headers = array("Cookie: sid=" . $good_sid . "; token=" . $good_logout_token); $headers = array("Cookie: sid=" . $good_sid . "; token=" . $good_logout_token);
111 112 $data = array('doit' => 1); $data = array('doit' => 1);
112 113 $r = do_req($test_url . "/op/logout?t=token_passed_by_cookie", $data, $headers); $r = do_req($test_url . "/op/logout?t=token_passed_by_cookie", $data, $headers);
113 114 if (stristr($r['body'], "You are now logged out")) { if (stristr($r['body'], "You are now logged out")) {
114 rg_log_ml(print_r($r, TRUE));
115 115 rg_log("No error on logout with token passed by cookie?! See above."); rg_log("No error on logout with token passed by cookie?! See above.");
116 116 exit(1); exit(1);
117 117 } }
118 rg_log_exit();
118 119
119 120
120 rg_log("Testing logout CSRF (good token)...");
121 rg_log_enter("Testing logout CSRF (good token)...");
122 test_set_ua("user-agent-1");
121 123 $url = $test_url . "/op/logout?t=good_token&token=" . $good_logout_token; $url = $test_url . "/op/logout?t=good_token&token=" . $good_logout_token;
122 $data['token'] = $good_token;
124 $data = array();
123 125 $r = do_req($url, $data, $headers); $r = do_req($url, $data, $headers);
124 126 if (!stristr($r['body'], "You are now logged out")) { if (!stristr($r['body'], "You are now logged out")) {
125 rg_log_ml(print_r($r, TRUE));
126 127 rg_log("Seems I cannot logout with a good token! See above."); rg_log("Seems I cannot logout with a good token! See above.");
127 128 exit(1); exit(1);
128 129 } }
130 rg_log_exit();
129 131
130 132 rg_log("OK!"); rg_log("OK!");
131 133 ?> ?>
File tests/http_login.php changed (mode: 100644) (index 651b2ef..1d55066)
... ... if ($r === FALSE) {
31 31 exit(1); exit(1);
32 32 } }
33 33 $good_sid = $r['sid']; $good_sid = $r['sid'];
34 $good_token = $r['token'];
34 $good_token = $r['tokens']['login'];
35 35 rg_log("good: sid=$good_sid token=$good_token"); rg_log("good: sid=$good_sid token=$good_token");
36 36 if (strncmp($good_sid, "X", 1) != 0) { if (strncmp($good_sid, "X", 1) != 0) {
37 37 rg_log("Seems we did not get a pre-login session!"); rg_log("Seems we did not get a pre-login session!");
 
... ... if ($r === FALSE) {
50 50 } }
51 51 //rg_log_ml("After loading attacker login form, r: " . print_r($r, TRUE)); //rg_log_ml("After loading attacker login form, r: " . print_r($r, TRUE));
52 52 $bad_sid = $r['sid']; $bad_sid = $r['sid'];
53 $bad_token = $r['token'];
53 $bad_token = $r['tokens']['login'];
54 54 rg_log("bad: sid=$bad_sid token=$bad_token"); rg_log("bad: sid=$bad_sid token=$bad_token");
55 55
56 56 rg_log("Now we can attack, we use attacker token but user cookie..."); rg_log("Now we can attack, we use attacker token but user cookie...");
File tests/http_settings.php changed (mode: 100644) (index 88b3854..32ef9ca)
... ... $rg_cache_enable = TRUE;
23 23 $now = time(); $now = time();
24 24
25 25 rg_log("Test if caching works cache_enable=" . ($rg_cache_enable ? "true" : "false")); rg_log("Test if caching works cache_enable=" . ($rg_cache_enable ? "true" : "false"));
26 rg_cache_set("test::a", "1");
26 rg_cache_set("test::a", "1", 0);
27 27 $r = rg_cache_get("test::a"); $r = rg_cache_get("test::a");
28 28 if (strcmp($r, "1") != 0) { if (strcmp($r, "1") != 0) {
29 29 rg_log("Main cache (set) is not working!"); rg_log("Main cache (set) is not working!");
30 30 exit(1); exit(1);
31 31 } }
32 rg_cache_unset("test::a");
32 rg_cache_unset("test::a", RG_SOCKET_NO_WAIT);
33 33 $r = rg_cache_get("test::a"); $r = rg_cache_get("test::a");
34 34 if ($r !== FALSE) { if ($r !== FALSE) {
35 35 rg_log("Main cache (unset) is not working!"); rg_log("Main cache (unset) is not working!");
 
... ... $data = array();
50 50 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
51 51 $r = do_req($test_url . "/op/settings/change_pass?t=load_change_pass_form", $data, $headers); $r = do_req($test_url . "/op/settings/change_pass?t=load_change_pass_form", $data, $headers);
52 52 if (!strstr($r['body'], "action=\"/op/settings/change_pass\"")) { if (!strstr($r['body'], "action=\"/op/settings/change_pass\"")) {
53 file_put_contents("http_settings_change_pass.log", $r['body']);
54 53 rg_log_ml("Cannot load change pass form!"); rg_log_ml("Cannot load change pass form!");
55 54 exit(1); exit(1);
56 55 } }
57 $good_token = $r['token'];
56 $good_token = $r['tokens']['set_pass'];
58 57
59 58 rg_log("Posting change pass form"); rg_log("Posting change pass form");
60 59 $data = array( $data = array(
 
... ... $data = array(
67 66 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
68 67 $r = do_req($test_url . "/op/settings/change_pass?t=post_change_pass_form", $data, $headers); $r = do_req($test_url . "/op/settings/change_pass?t=post_change_pass_form", $data, $headers);
69 68 if (!strstr($r['body'], "Password was updated with success")) { if (!strstr($r['body'], "Password was updated with success")) {
70 file_put_contents("http_settings_change_pass.log", $r['body']);
71 69 rg_log_ml("Cannot change pass!"); rg_log_ml("Cannot change pass!");
72 70 exit(1); exit(1);
73 71 } }
 
... ... if (!strstr($r['body'], "Password was updated with success")) {
76 74 rg_log("Now, try to login with the old password"); rg_log("Now, try to login with the old password");
77 75 $r2 = test_login($test_url, $rg_ui, $junk); $r2 = test_login($test_url, $rg_ui, $junk);
78 76 if ($r2 !== FALSE) { if ($r2 !== FALSE) {
79 rg_log_ml("Seems we were able to login with the old password!");
77 rg_log("Seems we were able to login with the old password!");
80 78 exit(1); exit(1);
81 79 } }
82 80
 
... ... $data = array();
86 84 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
87 85 $r = do_req($test_url . "/op/settings/change_pass?t=load_change_pass_form", $data, $headers); $r = do_req($test_url . "/op/settings/change_pass?t=load_change_pass_form", $data, $headers);
88 86 if (!strstr($r['body'], "action=\"/op/settings/change_pass\"")) { if (!strstr($r['body'], "action=\"/op/settings/change_pass\"")) {
89 file_put_contents("http_settings_change_pass.log", $r['body']);
90 87 rg_log_ml("Cannot load change pass form!"); rg_log_ml("Cannot load change pass form!");
91 88 exit(1); exit(1);
92 89 } }
93 $good_token = $r['token'];
90 $good_token = $r['tokens']['set_pass'];
94 91 $data = array( $data = array(
95 92 "doit" => 1, "doit" => 1,
96 93 "token" => $good_token, "token" => $good_token,
 
... ... $data = array(
101 98 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
102 99 $r = do_req($test_url . "/op/settings/change_pass?t=change_back_the_password", $data, $headers); $r = do_req($test_url . "/op/settings/change_pass?t=change_back_the_password", $data, $headers);
103 100 if ($r === FALSE) { if ($r === FALSE) {
104 file_put_contents("http_settings_change_back.log", $r['body']);
105 101 rg_log_ml("Cannot change back the pass to aaaa!"); rg_log_ml("Cannot change back the pass to aaaa!");
106 102 exit(1); exit(1);
107 103 } }
 
... ... rg_log("Posting edit info form");
122 118 $session_time = intval($now / 393956); $session_time = intval($now / 393956);
123 119 $data = array( $data = array(
124 120 "doit" => 1, "doit" => 1,
125 "token" => $r['token'],
121 "token" => $r['tokens']['user_edit_hl'],
126 122 "uid" => 4, "uid" => 4,
127 123 "username" => $rg_ui['username'], "username" => $rg_ui['username'],
128 124 "realname" => $rg_ui['realname'], "realname" => $rg_ui['realname'],
 
... ... $data = array(
132 128 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
133 129 $r = do_req($test_url . "/op/settings/edit_info?t=post_edit_info_form", $data, $headers); $r = do_req($test_url . "/op/settings/edit_info?t=post_edit_info_form", $data, $headers);
134 130 if (!strstr($r['body'], "Information was updated with success")) { if (!strstr($r['body'], "Information was updated with success")) {
135 file_put_contents("http_settings_edit_info.log", $r['body']);
136 131 rg_log_ml("Cannot change back the pass to aaaa: " . print_r($r, TRUE)); rg_log_ml("Cannot change back the pass to aaaa: " . print_r($r, TRUE));
137 132 exit(1); exit(1);
138 133 } }
 
... ... $res = rg_sql_query($db, $sql);
143 138 $row = rg_sql_fetch_array($res); $row = rg_sql_fetch_array($res);
144 139 rg_sql_free_result($res); rg_sql_free_result($res);
145 140 if (strcmp($rg_ui['realname'], $row['realname']) != 0) { if (strcmp($rg_ui['realname'], $row['realname']) != 0) {
146 file_put_contents("http_settings_edit_info.log", $r['body']);
147 141 rg_log_ml("realname was not changed: " . print_r($row, TRUE)); rg_log_ml("realname was not changed: " . print_r($row, TRUE));
148 142 exit(1); exit(1);
149 143 } }
150 144 if ($row['plan_id'] != 5) { if ($row['plan_id'] != 5) {
151 file_put_contents("http_settings_edit_info.log", $r['body']);
152 145 rg_log_ml("plan_id was not changed: " . print_r($row, TRUE)); rg_log_ml("plan_id was not changed: " . print_r($row, TRUE));
153 146 exit(1); exit(1);
154 147 } }
155 148 if ($row['session_time'] != $session_time) { if ($row['session_time'] != $session_time) {
156 file_put_contents("http_settings_edit_info.log", $r['body']);
157 149 rg_log_ml("session_time was not changed: " . print_r($row, TRUE)); rg_log_ml("session_time was not changed: " . print_r($row, TRUE));
158 150 exit(1); exit(1);
159 151 } }
 
... ... if ($r === FALSE) {
168 160 rg_log("Cannot load form!"); rg_log("Cannot load form!");
169 161 exit(1); exit(1);
170 162 } }
171 if (empty($r['token'])) {
163 if (empty($r['tokens']['keys'])) {
172 164 rg_log_ml("token not found! r:" . print_r($r, TRUE)); rg_log_ml("token not found! r:" . print_r($r, TRUE));
173 165 exit(1); exit(1);
174 166 } }
175 167 rg_log("Posting keys form"); rg_log("Posting keys form");
176 168 $comment = "<xss>" . $rg_ui['uid']; $comment = "<xss>" . $rg_ui['uid'];
177 169 $key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+2OHaQiZzdwV4HQF9pCBbSQFaoM5Q0YmmRYDL8BUCjwClDgOLp9lQVN5XksoBx2t9INj6XrobjNc/GUF60c1Ald0FtjRl7nIZdYvKDutlxHcGUy6MHsVnCDviXQJD9Hm9fyuBLdy3/oadSCAaQYE/Tcf9rWt1NmhQ7560bCGmh4pw8N+XXAz2nQBCqvIK8VDoBbOOgFa/HOwBrKCgaGmcTGs5wRWHbw3+h6CO1vqEYcSCSqBPMG1JOMfMTuJ0aTXXEkSNPF+TVva85L4qrQslyHbn2JU1t7/HQsFnGtgF1o2AglIR2RbyMmr6axI51Srf20EB9/c9T3auYQipbw85"; $key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+2OHaQiZzdwV4HQF9pCBbSQFaoM5Q0YmmRYDL8BUCjwClDgOLp9lQVN5XksoBx2t9INj6XrobjNc/GUF60c1Ald0FtjRl7nIZdYvKDutlxHcGUy6MHsVnCDviXQJD9Hm9fyuBLdy3/oadSCAaQYE/Tcf9rWt1NmhQ7560bCGmh4pw8N+XXAz2nQBCqvIK8VDoBbOOgFa/HOwBrKCgaGmcTGs5wRWHbw3+h6CO1vqEYcSCSqBPMG1JOMfMTuJ0aTXXEkSNPF+TVva85L4qrQslyHbn2JU1t7/HQsFnGtgF1o2AglIR2RbyMmr6axI51Srf20EB9/c9T3auYQipbw85";
178 $data = array("add" => 1, "token" => $r['token'], "key" => $key . ' ' . $comment);
170 $data = array("add" => 1, "token" => $r['tokens']['keys'], "key" => $key . ' ' . $comment);
179 171 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
180 172 $r = do_req($test_url . "/op/settings/keys?t=post_key_form_add", $data, $headers); $r = do_req($test_url . "/op/settings/keys?t=post_key_form_add", $data, $headers);
181 173 if ($r === FALSE) { if ($r === FALSE) {
182 file_put_contents("http_settings_key.log", $r['body']);
183 174 rg_log_ml("Cannot upload key: " . print_r($r, TRUE)); rg_log_ml("Cannot upload key: " . print_r($r, TRUE));
184 175 exit(1); exit(1);
185 176 } }
 
... ... if ($r === FALSE) {
207 198 exit(1); exit(1);
208 199 } }
209 200 rg_log("Posting delete keys form"); rg_log("Posting delete keys form");
210 $data = array("delete" => 1, "token" => $r['token'], "key_delete_ids[$key_id]" => "on");
201 $data = array("delete" => 1, "token" => $r['tokens']['keys'], "key_delete_ids[$key_id]" => "on");
211 202 $headers = array("Cookie: sid=" . $good_sid); $headers = array("Cookie: sid=" . $good_sid);
212 203 $r = do_req($test_url . "/op/settings/keys?t=post_key_form_del", $data, $headers); $r = do_req($test_url . "/op/settings/keys?t=post_key_form_del", $data, $headers);
213 204 if (!strstr($r['body'], "Selected keys were removed with success.")) { if (!strstr($r['body'], "Selected keys were removed with success.")) {
214 file_put_contents("http_settings_key_del.log", $r['body']);
215 205 rg_log_ml("Cannot delete key!"); rg_log_ml("Cannot delete key!");
216 206 exit(1); exit(1);
217 207 } }
File tests/token.php changed (mode: 100644) (index 1b1e866..07bae60)
... ... 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 $a = array("ua" => "user-agent1", "sid" => "session1");
18 $token = rg_token_get($db, $a);
17 $a = array("ua" => "user-agent1", "sid" => "session1", 'debug' => 1);
18 $token = rg_token_get($db, $a, 'tag1');
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);
 
... ... if ($token === FALSE) {
23 23 rg_log("Correct token: $token"); rg_log("Correct token: $token");
24 24
25 25 $a['token'] = $token; $a['token'] = $token;
26 $r = rg_token_valid($db, $a, FALSE);
26 $r = rg_token_valid($db, $a, 'tag1', FALSE);
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);
 
... ... if ($r === FALSE) {
32 32
33 33 rg_log("Now, test pre-login sessions..."); rg_log("Now, test pre-login sessions...");
34 34 $rg_token = FALSE; /* we must remove it from memory */ $rg_token = FALSE; /* we must remove it from memory */
35 $a = array("ua" => "user-agent1", "sid" => "Xsession2");
36 $token = rg_token_get($db, $a);
35 $a = array("ua" => "user-agent1", "sid" => "Xsession2", 'debug' => 1);
36 $token = rg_token_get($db, $a, 'tag2');
37 37 if ($token === FALSE) { if ($token === FALSE) {
38 38 rg_log("Generating a token should not fail (" . rg_token_error() . ")!"); rg_log("Generating a token should not fail (" . rg_token_error() . ")!");
39 39 exit(1); exit(1);
 
... ... $a['token'] = $token;
43 43
44 44 $copy = $a; $copy = $a;
45 45 $copy['token'] = "y" . substr($a['token'], 1); $copy['token'] = "y" . substr($a['token'], 1);
46 $r = rg_token_valid($db, $copy, FALSE);
46 $r = rg_token_valid($db, $copy, 'tag2', FALSE);
47 47 if ($r !== FALSE) { if ($r !== FALSE) {
48 48 rg_log("An altered token must return error!"); rg_log("An altered token must return error!");
49 49 exit(1); exit(1);
50 50 } }
51 51
52 $r = rg_token_valid($db, $a, FALSE);
52 $r = rg_token_valid($db, $a, 'tag2', FALSE);
53 53 if ($r === FALSE) { if ($r === FALSE) {
54 54 rg_log("Validating a correct token must work (" . rg_token_error() . ")!"); rg_log("Validating a correct token must work (" . rg_token_error() . ")!");
55 55 exit(1); exit(1);
 
... ... if ($r === FALSE) {
59 59 rg_log("Testing double posting..."); rg_log("Testing double posting...");
60 60 $rg_token = FALSE; /* we must remove it from memory */ $rg_token = FALSE; /* we must remove it from memory */
61 61 $a = array("ua" => "user-agent3", $a = array("ua" => "user-agent3",
62 "sid" => "session_double");
63 $token = rg_token_get($db, $a);
62 "sid" => "session_double",
63 'debug' => 1);
64 $token = rg_token_get($db, $a, 'tag3');
64 65 if ($token === FALSE) { if ($token === FALSE) {
65 66 rg_log("Generating a token should not fail (" . rg_token_error() . ")!"); rg_log("Generating a token should not fail (" . rg_token_error() . ")!");
66 67 exit(1); exit(1);
67 68 } }
68 69 $a['token'] = $token; $a['token'] = $token;
69 70
70 $r = rg_token_valid($db, $a, FALSE);
71 $r = rg_token_valid($db, $a, 'tag3', FALSE);
71 72 if ($r === FALSE) { if ($r === FALSE) {
72 73 rg_log("Calling 'valid' first time must work!"); rg_log("Calling 'valid' first time must work!");
73 74 exit(1); exit(1);
74 75 } }
75 $r = rg_token_valid($db, $a, FALSE);
76 $r = rg_token_valid($db, $a, 'tag3', FALSE);
76 77 if ($r !== FALSE) { if ($r !== FALSE) {
77 78 rg_log("Calling 'valid' second time must NOT work!"); rg_log("Calling 'valid' second time must NOT work!");
78 79 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