List of commits:
Subject Hash Author Date (UTC)
Some clients, for exampple JGit sends the request gzipped. Deal with it. Thanks Gabi for the report! ea9023af24a172724ec22313c8c0c15cc88f90df Catalin(ux) M. BOIE 2017-02-24 19:47:29
Switch to quotes to be able to use commas; small corrections ab27969287d666d0fb526f7b24b04f65ab7d54f7 Catalin(ux) M. BOIE 2017-02-14 18:28:13
Added more info to comparison and added baloons (Stig suggestion) 07c13312204980b85229acf7f0ab1e3a66aa6677 Catalin(ux) M. BOIE 2017-02-13 18:31:41
Comparison updated based on Stig's help! Thanks! d45c87235c003153b0579d9d875b62a0f6e0f209 Catalin(ux) M. BOIE 2017-02-13 17:54:00
Corrected a ORDER before WHERE affecting the listing of the users in admin section ee889bb3e9fb175af625cc5dab26c079fe6a6108 Catalin(ux) M. BOIE 2017-01-31 18:08:47
Bump version to v0.65 23209e409cae8a83b33b53b3cb3109a63be7bd8c Catalin(ux) M. BOIE 2017-01-30 18:52:26
Updates SELinux policy file fa9d4acd0c6ee730ee45c3e3ab57b55665e74666 Catalin(ux) M. BOIE 2017-01-30 18:51:52
Added credits for TLS setup about perfect forward secrecy 63ff4cf11961421d6f187d2597354d12eff9a810 Catalin(ux) M. BOIE 2017-01-30 18:51:31
Make more clear the text about Enterprise Edition 20a621f3de637975d93cbb260213c2d833a0acab Catalin(ux) M. BOIE 2017-01-30 18:50:50
TODO updates 29e7ddcea2ed6add27a13dfef09c8660d4b3520e Catalin(ux) M. BOIE 2017-01-30 18:49:28
Use IdentitiesOnly when setup SSH config for RocketGit fbd5d71c0341f9187cfd677d2d620749d09c61d6 Catalin(ux) M. BOIE 2017-01-30 18:49:10
Fixed push by HTTP; fixing some tests af00ea421d6eec2877cab0c37f9c492fff3860ec Catalin(ux) M. BOIE 2017-01-30 18:48:19
If user is suspended or deleted, show an error c308a9b435c9e5baa39ac3529c794df227ab9196 Catalin(ux) M. BOIE 2017-01-06 07:12:32
Allow users to delete their account 2a2338aca850737f16febc056c1d248daf935736 Catalin(ux) M. BOIE 2016-12-30 12:49:48
Improved TLS cyphers list for better security 00f1ad9bffc47d0cd786e6caa6f9777fae27b2ff Catalin(ux) M. BOIE 2016-12-30 12:47:54
Corrected the api key mail 3ac431ae8e880ceebc18507383771b23ce5d9b6a Catalin(ux) M. BOIE 2016-12-08 04:20:30
Big Amazon fixes f185636cf44652a2da9779ab21979807b91cf48f Catalin(ux) M. BOIE 2016-12-07 20:38:54
Typos, some additions for hints, TODO a0b3ff70ddcdfa28770b6467b03332b70cf38067 Catalin(ux) M. BOIE 2016-12-07 20:37:47
events.php missed apikeys include e6370414e0bef923fb5d1f639b8a7738fb8d1641 Catalin(ux) M. BOIE 2016-12-07 20:34:05
Improved the functional tests 935c1f0f62aba1ca75fce124a33593e7e900a83a Catalin(ux) M. BOIE 2016-12-07 20:33:33
Commit ea9023af24a172724ec22313c8c0c15cc88f90df - Some clients, for exampple JGit sends the request gzipped. Deal with it. Thanks Gabi for the report!
Author: Catalin(ux) M. BOIE
Author date (UTC): 2017-02-24 19:47
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2017-02-24 19:47
Parent(s): ab27969287d666d0fb526f7b24b04f65ab7d54f7
Signer:
Signing key:
Signing status: N
Tree: ef889d625609b02477c2dc00d0a5dfda647471f8
File Lines added Lines deleted
inc/repo.inc.php 6 6
inc/user.inc.php 52 9
inc/util.inc.php 2 0
tests/by_http.php 30 4
tests/http.inc.php 1 0
File inc/repo.inc.php changed (mode: 100644) (index bd16481..8f66464)
... ... function rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
2421 2421 if (strncasecmp($cmd, 'git-upload-pack', 15) == 0) { if (strncasecmp($cmd, 'git-upload-pack', 15) == 0) {
2422 2422 $cmd = 'git-upload-pack'; $cmd = 'git-upload-pack';
2423 2423 $needed_rights = 'F'; $needed_rights = 'F';
2424 $push = 0;
2424 $ret['push'] = 0;
2425 2425 } else if (strncasecmp($cmd, 'git-receive-pack', 16) == 0) { } else if (strncasecmp($cmd, 'git-receive-pack', 16) == 0) {
2426 2426 $cmd = 'git-receive-pack'; $cmd = 'git-receive-pack';
2427 2427 // We need push or anonymous push // We need push or anonymous push
2428 2428 $needed_rights = 'P|H'; $needed_rights = 'P|H';
2429 $push = 1;
2429 $ret['push'] = 1;
2430 2430 } else { } else {
2431 2431 $ret['error'] = 'Unknown command'; $ret['error'] = 'Unknown command';
2432 2432 break; break;
 
... ... function rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
2515 2515 // give the user a chance to authenticate. // give the user a chance to authenticate.
2516 2516 // TODO: change rg_rights_allow to return what rights are // TODO: change rg_rights_allow to return what rights are
2517 2517 // allowed and use it. // allowed and use it.
2518 if ($push == 1) {
2518 if ($ret['push'] == 1) {
2519 2519 $x['needed_rights'] = 'P'; $x['needed_rights'] = 'P';
2520 2520 $r = rg_rights_allow($db, $x); $r = rg_rights_allow($db, $x);
2521 2521 if ($r === TRUE) if ($r === TRUE)
 
... ... function rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
2528 2528 // For git protocol we cannot because we do not have the // For git protocol we cannot because we do not have the
2529 2529 // username/uid of the connecting user. // username/uid of the connecting user.
2530 2530 if (isset($_SERVER['SSH_CONNECTION'])) { if (isset($_SERVER['SSH_CONNECTION'])) {
2531 if (($ret['ri']['public'] == 0) || ($push == 1)) {
2531 if (($ret['ri']['public'] == 0) || ($ret['push'] == 1)) {
2532 2532 $r = rg_totp_verify_ip($db, $login_ui['uid'], $r = rg_totp_verify_ip($db, $login_ui['uid'],
2533 2533 $ip); $ip);
2534 2534 if (($r['ok'] !== 1) if (($r['ok'] !== 1)
 
... ... function rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
2546 2546 // TODO: limit io // TODO: limit io
2547 2547 // TODO: put process in a cgroup? // TODO: put process in a cgroup?
2548 2548
2549 if (($push == 1)
2549 if (($ret['push'] == 1)
2550 2550 && rg_user_over_limit($db, $ret['owner_ui'], $max)) { && rg_user_over_limit($db, $ret['owner_ui'], $max)) {
2551 2551 // TODO: be aware that a push may mean a delete => // TODO: be aware that a push may mean a delete =>
2552 2552 // free space?! // free space?!
 
... ... function rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
2572 2572 putenv('ROCKETGIT_IP=' . $ip); putenv('ROCKETGIT_IP=' . $ip);
2573 2573 putenv('ROCKETGIT_ITIME=' . microtime(TRUE)); putenv('ROCKETGIT_ITIME=' . microtime(TRUE));
2574 2574 putenv('ROCKETGIT_HOST=' . $host); putenv('ROCKETGIT_HOST=' . $host);
2575 if (($push == 1) && $need_namespace_copy) {
2575 if (($ret['push'] == 1) && $need_namespace_copy) {
2576 2576 $namespace = 'rg_' . rg_id(8); $namespace = 'rg_' . rg_id(8);
2577 2577 rg_log('namespace is ' . $namespace); rg_log('namespace is ' . $namespace);
2578 2578 putenv('GIT_NAMESPACE=' . $namespace); putenv('GIT_NAMESPACE=' . $namespace);
File inc/user.inc.php changed (mode: 100644) (index f1763f6..2bf438c)
... ... function rg_user_list_to_full_info($db, $list)
1848 1848 return $ret; return $ret;
1849 1849 } }
1850 1850
1851 /*
1852 * This function deals with incoming compressed input.
1853 * Please note that if the webserver was configured without an input filter
1854 * (like apache's SetInputFilter DEFLATE), this function will
1855 * take care of it.
1856 * Returns the uncompressed stream.
1857 */
1858 function rg_process_gzip($content_length, $content_encoding)
1859 {
1860 rg_log('DEBUG: process_gzip: cl=' . $content_length
1861 . ' content_encoding=' . $content_encoding);
1862
1863 $data_in = @file_get_contents('php://input');
1864 if ($data_in === FALSE) {
1865 rg_log('Cannot get in stream (1)!');
1866 return FALSE;
1867 }
1868
1869 rg_log('DEBUG: data_in: ' . substr($data_in, 0, 32));
1870 if (strcmp($content_encoding, 'gzip') == 0) {
1871 $data_in = @gzdecode($data_in);
1872 if ($data_in === FALSE) {
1873 rg_log('Cannot decompress!');
1874 return FALSE;
1875 }
1876 rg_log('DEBUG: after decompress: ' . substr($data_in, 0, 32));
1877 }
1878
1879 return $data_in;
1880 }
1881
1851 1882 /* /*
1852 1883 * Deals with push/fetch by HTTP(S) * Deals with push/fetch by HTTP(S)
1853 1884 */ */
 
... ... function rg_user_http_git($db, $rg, $paras)
1930 1961 $r = rg_repo_fetch_push_helper($db, $host, $rg['ip'], $r = rg_repo_fetch_push_helper($db, $host, $rg['ip'],
1931 1962 $rg['login_ui'], $prefix, $user, $repo, $service, $rg['login_ui'], $prefix, $user, $repo, $service,
1932 1963 $need_namespace_copy); $need_namespace_copy);
1933 //rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE));
1964 rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE));
1934 1965 if ($r['ok'] !== 1) { if ($r['ok'] !== 1) {
1935 1966 rg_log('DEBUG: set errror: ' . $r['error']); rg_log('DEBUG: set errror: ' . $r['error']);
1936 1967 header('X-Rocketgit-Error: ' . $r['error']); header('X-Rocketgit-Error: ' . $r['error']);
 
... ... function rg_user_http_git($db, $rg, $paras)
1979 2010 rg_log('DEBUG: push_allowed=' . $r['push_allowed'] rg_log('DEBUG: push_allowed=' . $r['push_allowed']
1980 2011 . ' empty_user=' . ($empty_user ? 'yes' : 'no') . ' empty_user=' . ($empty_user ? 'yes' : 'no')
1981 2012 . ' authd=' . ($authd === TRUE ? 'yes' : 'no') . ' authd=' . ($authd === TRUE ? 'yes' : 'no')
1982 . ' exists=' . $auth_ui['exists']);
1983 if ($r['push_allowed'] !== 1) {
2013 . ' exists=' . $auth_ui['exists']
2014 . ' push=' . $r['push']);
2015 if (($r['push'] === 1) && ($r['push_allowed'] !== 1)) {
1984 2016 // We have only anon push rights at this point. // We have only anon push rights at this point.
1985 2017 // If user is correct, but password not, we will ask // If user is correct, but password not, we will ask
1986 2018 // the user to try again. If user is not correct, // the user to try again. If user is not correct,
 
... ... function rg_user_http_git($db, $rg, $paras)
1993 2025 . ' realm="Use empty user if you have no account"'); . ' realm="Use empty user if you have no account"');
1994 2026 break; break;
1995 2027 } }
1996 } else {
2028 } else if ($r['push'] === 1) {
1997 2029 rg_log('DEBUG: user has full push rights'); rg_log('DEBUG: user has full push rights');
2030 } else {
2031 rg_log('DEBUG: it is a fetch');
1998 2032 } }
1999 2033
2034 $content_length = rg_var_str('CONTENT_LENGTH');
2035 $content_encoding = rg_var_str('HTTP_CONTENT_ENCODING');
2036 rg_log('DEBUG: cl=' . $content_length . ' ce=' . $content_encoding);
2037
2000 2038 if (strcmp($file, 'info/refs') == 0) { if (strcmp($file, 'info/refs') == 0) {
2001 2039 rg_log('DEBUG: info/refs'); rg_log('DEBUG: info/refs');
2002 2040 // TODO: we should allow this only if the connecting user has // TODO: we should allow this only if the connecting user has
 
... ... function rg_user_http_git($db, $rg, $paras)
2036 2074 . ' --stateless-rpc' . ' --stateless-rpc'
2037 2075 . ' ' . escapeshellarg($repo_path); . ' ' . escapeshellarg($repo_path);
2038 2076
2039 $data_in = @file_get_contents('php://input');
2077 $data_in = rg_process_gzip($content_length, $content_encoding);
2078 if ($data_in === FALSE)
2079 break;
2080
2040 2081 $e = rg_exec($run, $data_in, 'rg_echo', 'rg_git_band_2'); $e = rg_exec($run, $data_in, 'rg_echo', 'rg_git_band_2');
2041 2082 if ($e['code'] != 0) if ($e['code'] != 0)
2042 2083 rg_log('Error executing command: ' . $e['errmsg']); rg_log('Error executing command: ' . $e['errmsg']);
 
... ... function rg_user_http_git($db, $rg, $paras)
2048 2089 rg_git_info_pack("\x02", '== Welcome to RocketGit! =='); rg_git_info_pack("\x02", '== Welcome to RocketGit! ==');
2049 2090 rg_git_info_pack("\x02", 'you are connecting from IP ' rg_git_info_pack("\x02", 'you are connecting from IP '
2050 2091 . $rg['ip'] . '.'); . $rg['ip'] . '.');
2051 // If user does not correct to the correct URL, correct them
2092 // If user does not connect to the correct URL, correct them
2052 2093 if (!empty($host) && (strcasecmp($host, $rg['rg_http_host_no_port']) != 0)) if (!empty($host) && (strcasecmp($host, $rg['rg_http_host_no_port']) != 0))
2053 2094 rg_git_info_pack("\x02", 'Please use ' . $rg['rg_http_host_no_port'] rg_git_info_pack("\x02", 'Please use ' . $rg['rg_http_host_no_port']
2054 2095 . ' instead of ' . $host . '.'); . ' instead of ' . $host . '.');
 
... ... function rg_user_http_git($db, $rg, $paras)
2058 2099 . ' --stateless-rpc' . ' --stateless-rpc'
2059 2100 . ' ' . escapeshellarg($repo_path); . ' ' . escapeshellarg($repo_path);
2060 2101
2061 $data_in = @file_get_contents('php://input');
2062 //rg_log('DEBUG: data_in=' . $data_in);
2063 file_put_contents('/tmp/data_in', $data_in);
2102 $data_in = rg_process_gzip($content_length, $content_encoding);
2103 if ($data_in === FALSE)
2104 break;
2105
2064 2106 $e = rg_exec($run, $data_in, 'rg_echo', 'rg_echo'); $e = rg_exec($run, $data_in, 'rg_echo', 'rg_echo');
2065 2107 if ($e['code'] != 0) if ($e['code'] != 0)
2066 2108 rg_log('Error executing command: ' . $e['errmsg']); rg_log('Error executing command: ' . $e['errmsg']);
2067 2109 } else { } else {
2068 2110 rg_log('Unknown service!'); rg_log('Unknown service!');
2111 // TODO: send some errors, also above
2069 2112 } }
2070 2113
2071 2114 break; break;
File inc/util.inc.php changed (mode: 100644) (index e367f6f..d0dee08)
... ... function rg_exec($cmd, $input, $cb_stdout, $cb_stderr)
1083 1083 } else { } else {
1084 1084 //rg_log('DEBUG: fd is pipes[2], call stdout cb:' . $_d); //rg_log('DEBUG: fd is pipes[2], call stdout cb:' . $_d);
1085 1085 $cb_stderr($_d); $cb_stderr($_d);
1086 // We want the last error message to be able to log something
1087 $ret['stderr'] = $_d;
1086 1088 } }
1087 1089 } else if ($fd === $pipes[1]) { } else if ($fd === $pipes[1]) {
1088 1090 if ($cb_stdout === FALSE) { if ($cb_stdout === FALSE) {
File tests/by_http.php changed (mode: 100644) (index b8162a6..1676be2)
... ... putenv('GIT_ASKPASS=' . dirname(__FILE__) . '/ask_pass');
76 76 $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o x.strace git push --verbose origin master', '', FALSE, FALSE); $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o x.strace git push --verbose origin master', '', FALSE, FALSE);
77 77 if ($r['ok'] != 1) { if ($r['ok'] != 1) {
78 78 rg_log_ml('out: ' . print_r($r, TRUE)); rg_log_ml('out: ' . print_r($r, TRUE));
79 rg_log('Seems I can push master with authentication!');
79 rg_log('Seems I cannot push master with authentication!');
80 exit(1);
81 }
82 rg_log_exit();
83
84
85 rg_log('');
86 rg_log_enter('Trying to fetch master (with user/pass)...');
87 putenv('GIT_ASKPASS=' . dirname(__FILE__) . '/ask_pass');
88 $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o x.strace git fetch --verbose origin master', '', FALSE, FALSE);
89 if ($r['ok'] != 1) {
90 rg_log_ml('out: ' . print_r($r, TRUE));
91 rg_log('Seems I cannot fetch master with authentication!');
80 92 exit(1); exit(1);
81 93 } }
82 94 rg_log_exit(); rg_log_exit();
 
... ... rg_log_exit();
85 97 rg_log(''); rg_log('');
86 98 rg_log_enter('Trying to push master (without user/pass; private repo)...'); rg_log_enter('Trying to push master (without user/pass; private repo)...');
87 99 putenv('GIT_ASKPASS=/bin/true'); putenv('GIT_ASKPASS=/bin/true');
88 $r = rg_exec('cd .by_http && git push origin2 master', '', FALSE, FALSE);
100 $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o push_no_user.strace'
101 . ' git push --verbose origin2 master', '', FALSE, FALSE);
89 102 if ($r['ok'] == 1) { if ($r['ok'] == 1) {
90 103 rg_log_ml('out: ' . print_r($r, TRUE)); rg_log_ml('out: ' . print_r($r, TRUE));
91 104 rg_log('Seems I can push master without authentication (anonymous push)!'); rg_log('Seems I can push master without authentication (anonymous push)!');
 
... ... rg_log_exit();
102 115 rg_log(''); rg_log('');
103 116 rg_log_enter('Trying to push master (with user/pass; private repo)...'); rg_log_enter('Trying to push master (with user/pass; private repo)...');
104 117 putenv('GIT_ASKPASS=' . dirname(__FILE__) . '/ask_pass'); putenv('GIT_ASKPASS=' . dirname(__FILE__) . '/ask_pass');
105 $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o x2.strace git push --verbose origin2 master', '', FALSE, FALSE);
118 $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o push_with_user.strace'
119 . ' git push --verbose origin2 master', '', FALSE, FALSE);
120 if ($r['ok'] != 1) {
121 rg_log_ml('out: ' . print_r($r, TRUE));
122 rg_log('Seems I cannot push master with authentication!');
123 exit(1);
124 }
125 rg_log_exit();
126
127
128 rg_log('');
129 rg_log_enter('Trying to fetch master (with user/pass; private repo)...');
130 putenv('GIT_ASKPASS=' . dirname(__FILE__) . '/ask_pass');
131 $r = rg_exec('cd .by_http && strace -s2000 -f -tt -o x2.strace git fetch --verbose origin2', '', FALSE, FALSE);
106 132 if ($r['ok'] != 1) { if ($r['ok'] != 1) {
107 133 rg_log_ml('out: ' . print_r($r, TRUE)); rg_log_ml('out: ' . print_r($r, TRUE));
108 rg_log('Seems I can push master with authentication!');
134 rg_log('Seems I cannot fetch master with authentication!');
109 135 exit(1); exit(1);
110 136 } }
111 137 rg_log_exit(); rg_log_exit();
File tests/http.inc.php changed (mode: 100644) (index 01923e2..89c22b0)
... ... function do_req($url, &$data, &$headers)
43 43 curl_setopt($c, CURLOPT_REFERER, $test_referer); curl_setopt($c, CURLOPT_REFERER, $test_referer);
44 44 curl_setopt($c, CURLOPT_CERTINFO, TRUE); curl_setopt($c, CURLOPT_CERTINFO, TRUE);
45 45 curl_setopt($c, CURLOPT_VERBOSE, TRUE); curl_setopt($c, CURLOPT_VERBOSE, TRUE);
46 curl_setopt($c, CURLOPT_ENCODING , 'gzip');
46 47
47 48 $err = @fopen('php://temp', 'w'); $err = @fopen('php://temp', 'w');
48 49 if ($err !== FALSE) { if ($err !== FALSE) {
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

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

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

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

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