![apache2 上的 git-http-backend 可以拉取但不能推送:远程:致命:不是 git 存储库:'。'](https://linux22.com/image/781678/apache2%20%E4%B8%8A%E7%9A%84%20git-http-backend%20%E5%8F%AF%E4%BB%A5%E6%8B%89%E5%8F%96%E4%BD%86%E4%B8%8D%E8%83%BD%E6%8E%A8%E9%80%81%EF%BC%9A%E8%BF%9C%E7%A8%8B%EF%BC%9A%E8%87%B4%E5%91%BD%EF%BC%9A%E4%B8%8D%E6%98%AF%20git%20%E5%AD%98%E5%82%A8%E5%BA%93%EF%BC%9A'%E3%80%82'.png)
(我必须将所有地方的“http”替换为“hxxp”,否则我无法发布它,因为显然this looks like spam
)
我已经在我的服务器(Debian,arm)上设置了git。
我使用git-http-backend
apache2,以便可以从外部访问存储库。
下载存储库没有问题,但无法推送:
4.b:~/pro> git clone hxxp://botcastle1a/git/testgit
Cloning into 'testgit'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
4.b:~/pro> cd testgit
4.b:~/pro/testgit> echo e > e.txt
4.b:~/pro/testgit> git add e.txt
4.b:~/pro/testgit> git commit -m e
[master e3d41ae] e
1 file changed, 1 insertion(+)
create mode 100644 e.txt
4.b:~/pro/testgit> git push
Username for 'hxxp://botcastle1a': b
Password for 'hxxp://b@botcastle1a':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 259 bytes | 259.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: fatal: not a git repository: '.'
error: remote unpack failed: unpack-objects abnormal exit
To http://botcastle1a/git/testgit
! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'hxxp://botcastle1a/git/testgit'
4.b:~/pro/testgit>
remote: fatal: not a git repository: '.'
这是什么意思?
显然,在进行推送时,服务器端的 git 突然发现自己不在存储库目录中,而是在其他地方?
但我不知道在哪里,为什么。
(特别是在下载时没有同样的问题)
或者如何调试它。
这是我的与 git 相关的 apache 安装文件git.conf
:
ScriptAlias /git/ /botm/bin/git/git-http-backend/
<Directory /botm/bin/git>
Require all granted
</Directory>
<Files "git-http-backend">
SetEnv GIT_PROJECT_ROOT /botm/git
AuthType Basic
AuthName "Git Access"
AuthUserFile /botm/git/.htpasswd
Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
Require valid-user
</Files>
git-http-backend
安装方法如下:
1a.b:/botm/src/git> make install
sed "s/###TARGET;/\/usr\/lib\/git-core\/git-http-backend/" exec.c > git-http-backend.c
gcc -g -Wall -o git-http-backend git-http-backend.c
chmod u+s git-http-backend
mkdir -p /botm/bin/git
cp -p git-http-backend /botm/bin/git
1a.b:/botm/src/git>
关于安装过程的一些解释:这里生成的文件git-http-backend.c
是:
#include <unistd.h>
#define TARGET "/usr/lib/git-core/git-http-backend"
int main(int argc, char *argv[], char *envp[])
{
int r;
r=execve(TARGET,argv,envp);
return r;
}
因此它除了调用原始的 之外什么都不做/usr/lib/git-core/git-http-backend
。我这样做是为了可以在编译的 上设置 SETUID 位/botm/bin/git/git-http-backend
,但不在原始的 上设置/usr/lib/git-core/git-http-backend
。这样 git 后端就不会以 apache 用户的身份运行www-data
,而是以拥有存储库的用户的身份运行b
。
我发现有人在遇到问题时提出了问题git-http-backend
,apache2
但他们没有和我一样的具体错误。
我真的不知道这里出了什么问题以及如何调试和修复它。
编辑以添加:
执行 git clone 时,这会添加到 apache 访问日志中:
192.168.1.34 - - [06/Nov/2022:10:21:27 +0000] "GET /git/testgit/info/refs?service=git-upload-pack HTTP/1.1" 200 680 "-" "git/2.20.1"
192.168.1.34 - - [06/Nov/2022:10:21:28 +0000] "POST /git/testgit/git-upload-pack HTTP/1.1" 200 794 "-" "git/2.20.1"
执行失败的 git push 时出现以下情况:
192.168.1.34 - - [06/Nov/2022:10:25:05 +0000] "GET /git/testgit/info/refs?service=git-receive-pack HTTP/1.1" 401 666 "-" "git/2.20.1"
192.168.1.34 - b [06/Nov/2022:10:25:17 +0000] "GET /git/testgit/info/refs?service=git-receive-pack HTTP/1.1" 200 527 "-" "git/2.20.1"
192.168.1.34 - b [06/Nov/2022:10:25:17 +0000] "POST /git/testgit/git-receive-pack HTTP/1.1" 200 438 "-" "git/2.20.1"
错误日志中未添加任何内容。
编辑以添加:
实际的 http 通信,由 wireshark 记录(我从日志中删除了身份验证数据)
GET /git/testgit/info/refs?service=git-receive-pack HTTP/1.1
Host: botcastle1a
User-Agent: git/2.20.1
Accept: */*
Accept-Encoding: deflate, gzip
Accept-Language: en-UK, en;q=0.9, *;q=0.8
Pragma: no-cache
HTTP/1.1 401 Unauthorized
Date: Sun, 06 Nov 2022 10:37:08 GMT
Server: Apache/2.4.52 (Debian)
WWW-Authenticate: Basic realm="Git Access"
Content-Length: 458
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested. Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.52 (Debian) Server at botcastle1a Port 80</address>
</body></html>
GET /git/testgit/info/refs?service=git-receive-pack HTTP/1.1
Host: botcastle1a
Authorization: Basic [I removed the authentication data]
User-Agent: git/2.20.1
Accept: */*
Accept-Encoding: deflate, gzip
Accept-Language: en-UK, en;q=0.9, *;q=0.8
Pragma: no-cache
HTTP/1.1 200 OK
Date: Sun, 06 Nov 2022 10:37:18 GMT
Server: Apache/2.4.52 (Debian)
Expires: Fri, 01 Jan 1980 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache, max-age=0, must-revalidate
Transfer-Encoding: chunked
Content-Type: application/x-git-receive-pack-advertisement
23
001f# service=git-receive-pack
0000
b3
00b3659a81dc0911a738fae0741e278354e8ee28cfd7 refs/heads/master.report-status report-status-v2 delete-refs side-band-64k quiet atomic ofs-delta object-format=sha1 agent=git/2.30.2
4
0000
0
POST /git/testgit/git-receive-pack HTTP/1.1
Host: botcastle1a
Authorization: Basic [I removed the authentication data]
User-Agent: git/2.20.1
Accept-Encoding: deflate, gzip
Content-Type: application/x-git-receive-pack-request
Accept: application/x-git-receive-pack-result
Content-Length: 412
0095659a81dc0911a738fae0741e278354e8ee28cfd7 af9d9c3a27bd0bff7597b2ab764358f7227b228a refs/heads/master. report-status side-band-64k agent=git/2.20.10000PACK.........
x...A
.0.F.}N.. [email protected].`c..`@._ ...g
....vi ^.S..j9$..g..T|..NZB#....hb.z1...RlgOey.l.._#>[^/.I..1/.....wMb{p...u.k.......p>...x.340031Q0.+.(a..2.o].._.G...6...-x..!DA*X.M....N.....Tx.......%.=...2x.K......pe...NG....;Z....o..O
HTTP/1.1 200 OK
Date: Sun, 06 Nov 2022 10:37:18 GMT
Server: Apache/2.4.52 (Debian)
Expires: Fri, 01 Jan 1980 00:00:00 GMT
Pragma: no-cache
Cache-Control: no-cache, max-age=0, must-revalidate
Transfer-Encoding: chunked
Content-Type: application/x-git-receive-pack-result
26
0026.fatal: not a git repository: '.'
5
0059.
54
0028unpack unpack-objects abnormal exit
0028ng refs/heads/master unpacker error
0000
4
0000
0
答案1
我找到了一个解决方案。
有趣的是,这个解决方案与我之前解决的另一个问题相同:
https://unix.stackexchange.com/a/719077/543092
我检查了我的 apache 配置,没有发现任何错误。与
教程中看到的示例唯一的不同是,我没有使用ScriptAlias
原始代码,而是git-http-backend
使用了包装器。
我暂时省略了我的包装器,问题remote: fatal: not a git repository: '.'
不再发生。
当然,我遇到了我首先试图避免的问题,即git-http-backend
以用户身份运行www-data
。
好的,那么我的包装器出了什么问题?
这remote: fatal: not a git repository: '.'
表明由于某种原因,git-http-backend
它试图在错误的地方寻找 git 存储库。
但它怎么找到它呢?
从这里开始:
SetEnv GIT_PROJECT_ROOT /botm/git
这将设置GIT_PROJECT_ROOT
环境变量。
那么包装器是否无法将变量传递给被调用的程序?
没有。
如图所示,它做得正确:
r=execve(TARGET,argv,envp);
所以我的下一个猜测是这又是 SETUID 的“错误”。git-http-backend
由于检测到了 SETUID,环境变量本身被删除了。
所以我曾经setreuid()
让“伪装”变得完美:
#include <unistd.h>
#include <errno.h>
#define TARGET "/usr/lib/git-core/git-http-backend"
int main(int argc, char *argv[], char *envp[])
{
uid_t euid;
gid_t egid;
int r;
euid = geteuid();
egid = getegid();
if ((r = setreuid(euid, euid)))
return (r = errno);
if ((r = setregid(egid, egid)))
return (r = errno);
r=execve(TARGET,argv,envp);
return r;
}
现在一切正常。