I'm still in the process of setting up my new server. Today, I migrated the Git repositories. I wanted a more secure setup, that is I don't want my web server to be able to read the repositories. (It spawns CGit, which has to read them somehow.)
So I created all repositories below /var/git/repositories
, such that
they are only readable by the system user "git".
However, that presents a problem to the CGit CGI: It cannot access the
repositories any more. My first approach was: Just chown git.git
/usr/lib/cgi-bin/cgit.cgi
and set the setuid bit on it.
But, alas, that will only make the CGit binary run with effective user ID "git". What's needed to actually access the files is a real user ID "git".
The only way to set the real user ID is to call setuid()
with
effective root privileges. So I created a wrapper that
setuid()
s to that ID (real an effective)That's what I came up with:
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
int main(int argc, char *argv[])
{
struct passwd *p;
uid_t git_uid = 0;
while((p = getpwent()) != NULL) {
if(strcmp(p->pw_name, "git"))
continue;
/* got user "git" */
git_uid = p->pw_uid;
}
endpwent();
if(!git_uid)
return 1;
setuid(git_uid);
execv("/usr/lib/cgi-bin/cgit.cgi", argv);
return 0;
}
Provide it with a Makefile... (beware, use real tabs!)
default:
gcc -Wall -o cgit-as-git.cgi cgit-as-git.c
install:
install -o root -g root -m 4755 cgit-as-git.cgi /usr/lib/cgi-bin
... and change the Lighttpd configuration accordingly:
$HTTP["host"] == "git.plenz.com" {
setenv.add-environment += ( "CGIT_CONFIG" => "/etc/cgit/plenz.com.conf" )
alias.url = (
"/cgit.css" => "/usr/share/cgit/cgit.css",
"/cgit.png" => "/usr/share/cgit/cgit.png",
"/cgit.cgi" => "/usr/lib/cgi-bin/cgit-as-git.cgi",
"/" => "/usr/lib/cgi-bin/cgit-as-git.cgi",
)
cgi.assign = ( ".cgi" => "" )
url.rewrite-once = (
"^/cgit\.(css|png)" => "$0",
"^/.+" => "/cgit.cgi$0"
)
}
Done! Lighttpd can now call CGit as if it was a "usual" binary, but it will get wrapped and get the real and effective user ID of the system's user "git".
N.B.: If you want to use the wrapper as well, you might want to change
the (hard coded) user name "git" and the binary (see execv
call).