commit - 4de57f7d18150d208973cc4b070938b8117cb022
commit + b3bda0d35a32998d1ceef46bc5b0eb5813e59d9b
blob - 9ea84ce89d0ac18d3086ed46136515c5d7822a0c
blob + 41cf26b122f2b7e4948081a7d3523211aa4cd99f
--- gotsysd/libexec/gotsys-useradd/gotsys-useradd.c
+++ gotsysd/libexec/gotsys-useradd/gotsys-useradd.c
STAILQ_FOREACH_SAFE(user, &adduser_users, entry, tmp) {
uid_t uid;
- err = gotsys_conf_validate_name(user->name, "user");
- if (err)
- goto done;
- if (user->password) {
- err = gotsys_conf_validate_password(user->name,
- user->password);
+ if (strcmp(user->name, "anonymous") == 0) {
+ if (user->password == NULL ||
+ user->password[0] != '\0') {
+ err = got_error_msg(GOT_ERR_PRIVSEP_MSG,
+ "the \"anonymous\" user must use an "
+ "empty password");
+ goto done;
+ }
+ } else {
+ err = gotsys_conf_validate_name(user->name, "user");
if (err)
goto done;
+ if (user->password) {
+ err = gotsys_conf_validate_password(user->name,
+ user->password);
+ if (err)
+ goto done;
+ }
}
STAILQ_REMOVE(&adduser_users, user, gotsys_user, entry);
blob - 376e0f47ac088150a0fa8a928f83380dc7736240
blob + 85ffb48b610175195bc6fccdf7c94cba6d458279
--- gotsysd/libexec/gotsys-userhome/gotsys-userhome.c
+++ gotsysd/libexec/gotsys-userhome/gotsys-userhome.c
if (err->code != GOT_ERR_PARSE_CONFIG)
break;
/*
- * Ignore existing users with invalid names.
+ * Ignore existing users with invalid names
+ * except "anonymous".
* Such users were not created by us.
*/
err = NULL;
- goto next;
+ if (strcmp(pw->pw_name, "anonymous") != 0)
+ goto next;
}
/*
* Ignore existing users in our UID range which do
blob - 1d13bf576a50e4592ab5f54dda2741b80d8cead0
blob + eeef346dec6e5b64679f262f7edd5f89fc800fcc
--- gotsysd/sysconf.c
+++ gotsysd/sysconf.c
enum gotsysd_sysconf_state state;
uid_t uid_start;
uid_t uid_end;
+ int have_anonymous_user;
} gotsysd_sysconf;
static struct gotsys_conf gotsysconf;
return NULL;
}
+static const struct got_error *
+add_anonymous_user(struct gotsys_userlist *users)
+{
+ const struct got_error *err;
+ struct gotsys_user *user;
+
+ err = gotsys_conf_new_user(&user, "anonymous");
+ if (err)
+ return err;
+ user->password = strdup("");
+ if (user->password == NULL) {
+ err = got_error_from_errno("strdup");
+ gotsys_user_free(user);
+ return err;
+ }
+
+ STAILQ_INSERT_TAIL(&gotsysconf.users, user, entry);
+ return NULL;
+}
+
static void
sysconf_dispatch_libexec(int fd, short event, void *arg)
{
&gotsysconf.users, &gotsysconf.groups);
if (err)
break;
+ if (!gotsysd_sysconf.have_anonymous_user &&
+ strcmp(rule->identifier, "anonymous") == 0) {
+ err = add_anonymous_user(&gotsysconf.users);
+ if (err)
+ break;
+ gotsysd_sysconf.have_anonymous_user = 1;
+ }
rules = &gotsysd_sysconf.repo_cur->access_rules;
STAILQ_INSERT_TAIL(rules, rule, entry);
break;
gotsysd_sysconf.state =
SYSCONF_STATE_INSTALL_AUTHORIZED_KEYS;
user = STAILQ_FIRST(&gotsysconf.users);
+ if (user && strcmp(user->name, "anonymous") == 0)
+ user = STAILQ_NEXT(user, entry);
if (user == NULL) {
err = got_error_msg(GOT_ERR_PARSE_CONFIG,
"no users defined in configuration file");
log_debug("authorized keys installed for user %s",
gotsysd_sysconf.user_cur->name);
user = STAILQ_NEXT(gotsysd_sysconf.user_cur, entry);
+ if (user && strcmp(user->name, "anonymous") == 0)
+ user = STAILQ_NEXT(user, entry);
if (user) {
err = start_userkeys(iev, user);
if (err)
blob - 3d8ccf069840ef200e21b99bee10b0677212ddc4
blob + eac2e130716a0c60236d2758d09f5b859e2fac24
--- lib/gotsys_conf.c
+++ lib/gotsys_conf.c
"reference to undeclared group '%s' via "
"access rule", name);
}
- } else if (strcmp(name, "anonymous") != 0) {
+ } else if (strcmp(name, "anonymous") == 0) {
+ if (access == GOTSYS_ACCESS_PERMITTED &&
+ (authorization & GOTSYS_AUTH_WRITE)) {
+ return got_error_msg(GOT_ERR_PARSE_CONFIG,
+ "the \"anonymous\" user must not have write "
+ "permission");
+ }
+ } else {
struct gotsys_user *user = NULL;
STAILQ_FOREACH(user, users, entry) {
blob - d0985116bf402e07f13fb2a508a72f4455a47514
blob + 87abeb7c7095519d423cde7b9a91554386478b15
--- lib/gotsys_imsg.c
+++ lib/gotsys_imsg.c
offset = 0;
while (remain > 0) {
size_t namelen, pwlen, ulen;
+ int is_anonymous_user = 0;
if (remain < sizeof(iuser))
return got_error(GOT_ERR_PRIVSEP_LEN);
continue;
}
- err = gotsys_conf_validate_name(name, "user");
- if (err) {
- free(name);
- return err;
+ is_anonymous_user = (strcmp(name, "anonymous") == 0);
+ if (!is_anonymous_user) {
+ err = gotsys_conf_validate_name(name, "user");
+ if (err) {
+ free(name);
+ return err;
+ }
}
err = gotsys_conf_new_user(&user, name);
return err;
if (pwlen) {
+ if (is_anonymous_user) {
+ err = got_error_msg(GOT_ERR_PRIVSEP_MSG,
+ "the \"anonymous\" user must use an "
+ "empty password");
+ gotsys_user_free(user);
+ return err;
+ }
user->password = strndup(imsg->data + offset +
sizeof(iuser) + namelen, pwlen);
if (user->password == NULL) {
gotsys_user_free(user);
return err;
}
+ } else if (is_anonymous_user) {
+ user->password = strdup("");
+ if (user->password == NULL) {
+ err = got_error_from_errno("strdup");
+ gotsys_user_free(user);
+ return err;
+ }
}
#if 0
log_debug("user %s: password '%s' ssh key '%s'", user->name,
blob - 09d2632d1b6fdba13d7c7fdc738a5a6330e72fc5
blob + b670e5bee998649e54afac2f9b831ffdd87d57b4
--- regress/gotsysd/test_gotsysd.sh
+++ regress/gotsysd/test_gotsysd.sh
return 1
fi
- cat >> ${testroot}/wt/gotsys.conf <<EOF
+ crypted_vm_pw=`echo ${GOTSYSD_VM_PASSWORD} | encrypt | tr -d '\n'`
+ crypted_pw=`echo ${GOTSYSD_DEV_PASSWORD} | encrypt | tr -d '\n'`
+ sshkey=`cat ${GOTSYSD_SSH_PUBKEY}`
+ cat > ${testroot}/wt/gotsys.conf <<EOF
+group slackers
+
+user ${GOTSYSD_TEST_USER} {
+ password "${crypted_vm_pw}"
+ authorized key ${sshkey}
+}
+user ${GOTSYSD_DEV_USER} {
+ password "${crypted_pw}"
+ authorized key ${sshkey}
+}
+repository gotsys.git {
+ permit rw ${GOTSYSD_TEST_USER}
+ permit rw ${GOTSYSD_DEV_USER}
+}
repository "foo" {
permit rw ${GOTSYSD_DEV_USER}
}
test_done "$testroot" "$ret"
}
+test_user_anonymous() {
+ local testroot=`test_init user_anonymous 1`
+
+ # An attempt to grant write permissions to anonymus is an error.
+ cat > ${testroot}/bad-gotsys.conf <<EOF
+repository "gotsys" {
+ permit rw anonymous
+}
+EOF
+ gotsys check ${testroot}/bad-gotsys.conf \
+ > $testroot/stdout 2> $testroot/stderr
+ ret=$?
+ if [ $ret -eq 0 ]; then
+ echo "gotsys check suceeded unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ echo -n "gotsys: ${testroot}/bad-gotsys.conf: line 2: " \
+ > $testroot/stderr.expected
+ echo "the \"anonymous\" user must not have write permission" \
+ >> $testroot/stderr.expected
+ cmp -s $testroot/stderr.expected $testroot/stderr
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stderr.expected $testroot/stderr
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ got checkout -q $testroot/${GOTSYS_REPO} $testroot/wt >/dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got checkout failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ crypted_vm_pw=`echo ${GOTSYSD_VM_PASSWORD} | encrypt | tr -d '\n'`
+ crypted_pw=`echo ${GOTSYSD_DEV_PASSWORD} | encrypt | tr -d '\n'`
+ sshkey=`cat ${GOTSYSD_SSH_PUBKEY}`
+ cat > ${testroot}/wt/gotsys.conf <<EOF
+group slackers
+
+user ${GOTSYSD_TEST_USER} {
+ password "${crypted_vm_pw}"
+ authorized key ${sshkey}
+}
+user ${GOTSYSD_DEV_USER} {
+ password "${crypted_pw}"
+ authorized key ${sshkey}
+}
+repository gotsys.git {
+ permit rw ${GOTSYSD_TEST_USER}
+ permit rw ${GOTSYSD_DEV_USER}
+}
+repository "foo" {
+ permit rw ${GOTSYSD_DEV_USER}
+ permit ro anonymous
+}
+EOF
+ (cd ${testroot}/wt && got commit -m "add anonymus user" >/dev/null)
+ local commit_id=`git_show_head $testroot/${GOTSYS_REPO}`
+
+ got send -q -i ${GOTSYSD_SSH_KEY} -r ${testroot}/${GOTSYS_REPO}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got send failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ # Wait for gotsysd to apply the new configuration.
+ echo "$commit_id" > $testroot/stdout.expected
+ for i in 1 2 3 4 5; do
+ sleep 1
+ ssh -i ${GOTSYSD_SSH_KEY} root@${VMIP} \
+ cat /var/db/gotsysd/commit > $testroot/stdout
+ if cmp -s $testroot/stdout.expected $testroot/stdout; then
+ break;
+ fi
+ done
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "gotsysd failed to apply configuration" >&2
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ # The new repository should be readable anonymously.
+ got clone -q anonymous@${VMIP}:foo.git $testroot/foo-anonclone.git
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ echo "got clone failed unexpectedly" >&2
+ test_done "$testroot" 1
+ return 1
+ fi
+
+ test_done "$testroot" "$ret"
+}
+
test_parseargs "$@"
run_test test_user_add
run_test test_user_mod
run_test test_group_add
run_test test_group_del
run_test test_repo_create
+run_test test_user_anonymous