#define CFG_FILE "/etc/repo_shell.conf"
#define SHELL "/bin/bash"
+#define GIT_ACL_FILE ".gitacls"
+
+enum { REPO_UMASK = 027 };
typedef struct {
char *user;
struct passwd *pw = getpwnam(user);
if (!pw)
- die("invalid user %s", pw->pw_name);
+ die("invalid user %s", user);
+ setgid(pw->pw_gid);
setuid(pw->pw_uid);
}
+/* Set the user and group permissions back to the requesting user */
+static void reset_user()
+{
+ setgid(getgid());
+ setuid(getuid());
+}
+
static char *dequote(char *arg)
{
char* narg = NULL;
return narg;
}
-static char *add_prefix(char *prefix, char* arg)
+static char *add_prefix(const char *prefix, const char* arg)
{
- char *narg = arg;
+ char *narg;
int i;
if (arg && prefix && (i = strlen(prefix))) {
die("bad command");
change_user(cfg.owner);
+ umask(REPO_UMASK);
if (!git_check_access(cmd, arg, user))
die("insufficient ACL permissions");
int ret;
change_user(cfg.owner);
+ umask(REPO_UMASK);
return execvp(svnserve_argv[0], (char *const *) svnserve_argv);
}
if (!strcmp(name, "svn_root"))
pconfig->svn_root = xstrdup(value);
- else if (!strcmp(name, "git_root"))
+ else if (!strcmp(name, "git_root")) {
pconfig->git_root = xstrdup(value);
- else if (!strcmp(name, "owner"))
+ pconfig->git_acl_file = add_prefix(value, GIT_ACL_FILE);
+ } else if (!strcmp(name, "owner"))
pconfig->owner = xstrdup(value);
- else if (!strcmp(name, "git_acl_file"))
- pconfig->git_acl_file = xstrdup(value);
else if (!strcmp(name, "allow_interactive"))
pconfig->allow_interactive = str_has_word(value, pconfig->user);
else
die("opening /dev/null failed");
close (devnull_fd);
+ if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
+ fprintf(stderr, "%s is a replacement login shell.\n"
+ " May be ran from the command line with one of these options:\n"
+ " -h|--help this text\n"
+ " -v|--version program version string\n"
+ " -t|--test <user> <repo> test access\n"
+ " -d|--detail <user> <repo> test access, outputting more detail\n"
+ , argv[0]);
+ return 0;
+ }
+
if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))) {
fprintf(stderr, "%s\n", version);
return 0;
fprintf(stderr, "\n");
die("only repository access is allowed");
}
- setuid(getuid());
+ reset_user();
argv[0] = SHELL;
execvp(argv[0], (char *const *) argv);
return 1;
}
- if ((!strcmp(argv[1], "-t") || !strcmp(argv[1], "--test"))) {
+ if ((!strcmp(argv[1], "-d") || !strcmp(argv[1], "--detail"))) {
perms_t p;
if (argc !=4)
- die("usage: %s -t <user> <repo>", argv[0]);
+ die("usage: %s -d|--detail <user> <repo>", argv[0]);
p = git_acl(argv[2], argv[3], cfg.git_acl_file);
fprintf(stderr,
"user '%s' repo '%s' perms '%s'\n via userid '%s' repoid '%s'\n",
return 0;
}
+ if ((!strcmp(argv[1], "-t") || !strcmp(argv[1], "--test"))) {
+ perms_t p;
+
+ if (argc !=4)
+ die("usage: %s -t|--test <user> <repo>", argv[0]);
+ p = git_acl(argv[2], argv[3], cfg.git_acl_file);
+ printf("%s\n", git_acl_perms_as_str(p));
+ return 0;
+ }
+
if (argc == 3) {
/* argv[0] = repo_shell, argv[1] = -c, argv[2] = cmd
* cmd = "svnserve -t" or "git-xxx '/path/to/repo.git'"
if (!cfg.allow_interactive)
die("only repository access is allowed");
- setuid(getuid());
+ reset_user();
cd_to_homedir();
argv[0] = SHELL;
execvp(argv[0], (char *const *) argv);