User authentication on Savannah

User account creation

  1. Anyone can register a Savannah user account using the web interface:
  2. These user accounts are used across all Savannah systems.
  3. Users can upload ssh public keys using the web interface at:
  4. ssh public keys are stored in the MySQL database server on (see SavannahServices).

User information can be viewed by anyone on the Savannah web site. Example for user 'agn':

Database access

In the SQL database, currently but accessible from the collection of hosts, the following sql commands can be used to examine user accounts:

$ echo "select
          user_id, user_name, email, realname,
          uidNumber, authorized_keys
        from user
        where user_name = 'agn'" \
      | mysql savane

| user_id | user_name | email    | realname     | uidNumber | authorized_keys |
|   94790 | agn       | [email]  | Assaf Gordon |    131035 | ssh-rsa AAAAB3Nz|

The authorized_keys field contains all the user's SSH public keys, concatenated with a ### delimiter, as a one-line string. Users upload their GPG key and this data is stored in this database record. Some users have uploaded malformed and invalid GPG key information. Therefore some of these records are invalid due to having had invalid information uploaded.

Reactivating a user

It's possible to do this in the web interface: Main page -> Browse Users List -> find user -> [Activate] in the Actions column.

Also possible to do in sql, of course. Check the status, do the update as safely as possible, check again:

mysql> select user_id,user_name,status from user where user_name = 'FOO';
mysql> update user set status='A' where user_id=N and user_name='FOO' limit 1;
mysql> select user_id,user_name,status from user where user_name = 'FOO';

User/group accounts

In Savannah systems, there is a Unix user for each Savannah registered user:

 vcs0:~# getent passwd agn
 agn:x:131035:1003:Assaf Gordon:/srv:/usr/local/bin/sv_membersh

and a unix group for each Savannah registered project:

vcs0:~# getent group datamash

Access control is based on Unix group membership.


The gawk (GNU Awk) project ( has six members as of Nov. 2014 (

The git repository on is group-owned by gawk group:

vcs0:~# ls -ld /srv/git/gawk.git/
drwxrwsr-x 8 root gawk 4096 Nov  4 01:23 /srv/git/gawk.git/

The members of the gawk group are allowed to push code updates to the gawk repository:

vcs0:~# getent group gawk

Authentication mechanisms

For VCS repositories (git/hg/bzr/svn/cvs on and download/releases (on, users are authenticated using SSH access and their public keys. See SavannahServices for details about the available services on these servers.

Savannah users who are not members of any project (i.e., do not have write access to any repository) do not have ssh login access on vcs even if they have set up their ssh keys. getent passwd USER will return empty results for such users, even if they are valid users in the database (i.e., they exist in the users mysql table).

Technically, this is due to the libnss-mysql (see below) script doing an sql join on the user and user_group tables, and requiring having at least one record in the user_group table. Maybe someday this will be changed.

These servers use the MySQL database in two ways:

  • Unix user management, using nsswitch and libnss-mysql.
  • ssh key authentication, using the custom AuthorizedKeysExec option.

nsswitch and libnss-mysql

The files download0:/etc/nsswitch.conf and vcs0:/etc/nsswitch.conf contain the following configuration:

passwd:         compat mysql
group:          compat mysql
shadow:         compat mysql

Bob Proulx explains:

That is how libc is configured. 'compat' means /etc/passwd in the normal compatible way. 'mysql' means if not found in the first compat section then look it up in mysql. That is what allows libc to find users in the mysql database.

 download0:~# getent passwd agn
 agn:x:131035:1003:Assaf Gordon:/srv:/usr/local/bin/sv_membersh

The sql statements (to extract information from the mysql database on internal0) are defined in download0:/etc/libnss-mysql.cfg and vcs0:/etc/libnss-mysql.cfg.


Savannah users have two IDs in the database: user.user_id and user.uidNumber. user_id is used in the PHP web-frontend alone (it is the primary key for the user table). uidNumber is the user's unix account user id (used by getent above).

When a new user is registerd on savannah, the user_id will be unique but the uidNumber will be NULL.

A cron job (mgt0:/etc/cron.d/savannah) calls a script ( sv_assign_uid_gid) which scans the new users in the database, and creates unix user-ids and group ids if needed (if a user is not part of any group - they won't need ssh access and thus won't need user-id).

Search for sv_assign_uid_gid in SavannahInternals to see how it is called (but note that the page is out-dated: the script now runs as a cron job on mgt0, not internal0).

ssh authentication

The file /etc/ssh/sshd_config on download0: and vcs0: servers have the line: ... AuthorizedKeysExec /usr/local/bin/sv_get_authorized_keys ...

Historical Note:
AuthorizedKeysExec was a patch submitted by GNU Hacker Michael J. Flickinger ( to OpenSSH in 2011. It appears the patch was never formally accepted by upstream OpenSSH.
In 2012 a similar patch was accepted from RedHat using a differently named option AuthorizedKeysCommand.
This option (and not AuthorizedKeysExec) is available in most OpenSSH installations.
If Savannah servers are ever upgraded, these configuration files should be updated from AuthorizedKeysExec to AuthorizedKeysCommand.

When users login to Savannah servers using ssh, they specify the user account:

git clone

The user is therefore known, and OpenSSH needs to find the user's public keys. The /usr/local/bin/sv_get_authorized_keys Perl script simply queries the ssh public keys of the user (splitting them by ### delimiter):

my ($authorized_keys) = $dbd->selectrow_array(q[
    SELECT authorized_keys
    FROM user
    WHERE user_name = ?], undef, $user);

print join("\n", split('###', $authorized_keys));

Manually invoking sv_get_authorized_keys looks like:

vcs0:~# /usr/local/bin/sv_get_authorized_keys agn
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvs [...]

To validate the user's keys on vcs, use the following script:

vcs0:~# ~/bin/ agn
gordon@host1     2048 fe:61:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.9WvGnA/key.00 (RSA)
gordon@host2     2048 87:21:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.9WvGnA/key.01 (RSA)
gordon@host3     2048 3d:00:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.9WvGnA/key.02 (RSA)

vcs0:~# ~/bin/ someuser
someuser@host1   4096 6b:36:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.DmNCzP/key.00 (RSA)
someuser@host2   4096 0b:c3:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx /tmp/pubkey.check.DmNCzP/key.01 (RSA)
Invalid key: /tmp/pubkey.check.DmNCzP/key.02
Errors found in ssh pubkeys for user 'someuser'.
to troubleshoot, check files in /tmp/pubkey.check.DmNCzP .

The above script can help with troubleshooting user's SSH login problems.

mgt and root access is the management server (see SavannahArchitecture for more details).

root access to mgt0 (and from there to the other Savannah servers) is controlled by mgt0:/root/.ssh/authorized_keys. This file is updated manually by existing Savannah administrators, adding ssh public keys of authorized savannah hackers.

ssh access to mgt0 is only possible from fencepost (and other internal FSF machines to which no one outside the FSF has access). ssh access to vcs0 and download0 is open to all as required by their respective functions.

fencepost is the general-purpose server for GNU hackers (for more information:

It is managed by FSF sysadmin, and not managed by Savannah people in any way whatsoever.

Users on conventionally use the same username as Savannah accounts, and public ssh keys are copied (manually) from Savannah database (i.e., users requesting access to fencepost should setup accounts on Savannah with ssh public keys). Other than that - user management on fencepost is separate from the rest of Savannah servers.

Each user on fencepost has a home directory with ~/.ssh/authorized_keys files, enabling ssh access:

$ getent passwd agn
agn:x:1557:1562:Assaf Gordon,,,:/home/a/agn:/bin/bash

GNU webpages repository access for www members

Members of the www group (= GNU webmasters) have write access to the webpage repository for all gnu (not nongnu) projects. This is accomplished with ACLs. See ChangeLog entries by Beuc for 2006-06-28 and 2006-05-10, recorded in The key command is:

setfacl -m group:www:rw- FILES
setfacl -m default:group:www:rwx -m group:www:rwx DIRS

To set all of them I think this is needed. Testing it now.

setfacl -m group:www:rw- project/CVSROOT/history
find project/project -type d -exec setfacl -m default:group:www:rwx -m group:www:rwx {} +
find . -name CVSROOT -prune -o -type f -exec setfacl -m group:www:rw- {} +

The Savane module apparently installs this access for new gnu projects and directories.