#include <pwd.h>
#include <string.h>
#include "ini.h"
+#include "version.h"
#define CFG_FILE "/etc/repo_shell.cfg"
+#define GIT_ACL_FILE "git_acl.cfg"
typedef struct {
char *svn_root;
char *owner;
} cfg_t;
+static const char* shell_argv[] = { "/bin/bash", NULL };
+
#undef USE_DEFAULTS
#ifdef USE_DEFAULTS /* perhaps we want defaults? Not sure */
static cfg_t cfg {
static cfg_t cfg;
#endif
-#define alloc_nr(x) (((x)+16)*3/2)
-
-/*
- * Realloc the buffer pointed at by variable 'x' so that it can hold
- * at least 'nr' entries; the number of entries currently allocated
- * is 'alloc', using the standard growing factor alloc_nr() macro.
- *
- * DO NOT USE any expression with side-effect for 'x', 'nr', or 'alloc'.
- */
-#define ALLOC_GROW(x, nr, alloc) \
- do { \
- if ((nr) > alloc) { \
- if (alloc_nr(alloc) < (nr)) \
- alloc = (nr); \
- else \
- alloc = alloc_nr(alloc); \
- x = xrealloc((x), alloc * sizeof(*(x))); \
- } \
- } while (0)
-
-static inline void die(const char *fmt, ...)
+static void die(const char *fmt, ...)
{
va_list ap;
return ret;
}
-void *xrealloc(void *ptr, size_t size)
-{
- void *ret;
-
- ret = realloc(ptr, size);
- if (!ret && !size)
- ret = realloc(ptr, 1);
- if (!ret)
- die("Out of memory, realloc failed");
- return ret;
-}
-
static uid_t user_uid(char *user)
{
struct passwd *pw = getpwnam(user);
return 1; /* for now */
}
-static int git_check_access(const char *cmd, const char *arg, const char *user)
+static int git_acl(const char *user, const char *repo)
{
- /* TODO: Read some configuration file which maps users and access
- * to a boolean true/false value.
- *
- * The git command can support read and write.
- * git-receive-pack is ok for readers and writers
- * git-upload-pack is ok only for writers
- * git-upload-archive is ok only for writers
+ /* TODO: Read GIT_ACL_FILE from cfg.owner's home directory. Look for
+ * the access level afforded user for repo. A return of 0 means no
+ * access, a return of 1 means read only, and a return of 2 means
+ * read/write.
*/
- return 1; /* assume OK for now */
+#if 0
+ struct passwd *pw;
+ char *file;
+ int len = strlen(cfg.owner) + strlen(GIT_ACL_FILE) + 8;
+
+ pw = getpwnam(cfg.owner);
+ if (!pw)
+ die("owner %s has no passwd entry?", cfg.owner);
+ len = strlen(pw->pw_dir) + strlen(GIT_ACL_FILE) + 2;
+ file = xmalloc(sizeof(char) * len);
+ sprintf(file, "%s/%s", pw->pw_dir, GIT_ACL_FILE);
+ fprintf(stderr, "[someday check %s for git ACLs]\n", file);
+ free(file);
+#endif
+ return 2; /* assume read/write for now */
+}
+
+static int git_check_access(const char *cmd, const char *repo, const char *user)
+{
+ int rw = 1; /* 0=no access, 1=read only, 2=read/write */
+
+ /* What access is required per the incoming command? */
+ if (!strcmp(cmd, "git-upload-pack") ||
+ !strcmp(cmd, "git-upload-archive"))
+ rw = 2;
+
+ /* Return true (1) if the user permissions >= those required */
+ return (git_acl(user, repo) >= rw) ? 1 : 0;
}
static int do_git_cmd(const char *cmd, char *arg, char *user)
};
static int handler(void* user, const char* section, const char* name,
- const char* value)
+ const char* value)
{
cfg_t* pconfig = (cfg_t*)user;
die("opening /dev/null failed");
close (devnull_fd);
- if (argc < 3)
- die("invalid arguments");
+ if (argc == 2 && (!strcmp(argv[1], "-v") ||
+ !strcmp(argv[1], "--version"))) {
+ fprintf(stderr, "%s\n", version);
+ return 0;
+ }
+
+ if (argc == 1 && check_ssh_interactive(getuid())) {
+ setuid(getuid());
+ execvp(shell_argv[0], (char *const *) shell_argv);
+ }
#ifdef USE_DEFAULTS
ini_parse("repo_shell.cfg", handler, &cfg);
if (!check_ssh_interactive(getuid()))
die("only repository access is allowed");
+ setuid(getuid());
cd_to_homedir();
count = split_cmdline(prog, &user_argv);
if (count >= 0) {