OS Authentication ================= This document describes an "OS-level" authentication scheme for iRODS. The purpose of OS authentication is to allow iRODS to authorize users who have already logged into an iRODS client system using some form of OS configured authentication and authorization scheme (e.g. logged in using PAM, or via ssh authentication). The fact that a user is logged into a properly configured iRODS client node itself is proof of their identity. How it works ----------- The OS authentication modifies the existing iRODS username/password authentication. iRODS username and password works by having the iRODS server send a challenge to the calling client (i.e. a random string of bytes), which is then hashed along with the user's password into a response. This response is then compared with a similarly calculated hash on the iRODS ICAT-enabled server, by having the server look up the user's password in ICAT. The difference with OS authentication is that the user password is replaced by a generated "authenticator". This authenticator is a concatenation of the user's username, the user's uid, the challenge, and a shared secret, which is then MD5 hashed. This authenticator is then used in the same way that the password is used with username/password authentication. So what makes this more secure than just telling iRODS who I am, and having iRODS believe me (i.e. a "no authentication" mode)? Each element of the authenticator comes from a particular "trusted" mechanism, that together guard against spoofing (i.e. telling iRODS that I'm somebody I'm not). Let's examine the information in the authenticator generated by the client: - username - the username is provided to iRODS by the user (using the irodsUserName variable in .irodsEnv or the environment). - uid - the uid is retrieved by using the getuid() system call. On a non-compromised UNIX system, this is guaranteed to return the real uid of the calling process. Even if a process is 'setuid' to another uid (i.e. by using the 'setuid' mode bit on the executable, which sets the 'effective' uid of a process), the real uid is the actual user's uid. You can't fool the OS! - challenge - the challenge is a random set of bytes generated by the iRODS server for a particular client/agent connection. It should not be guessable for a given connection, and since it is different between connections, a given authenticator is "unique" for a connection. - shared secret - or key. This is a key that is placed in a file that is only readable by the iRODS service user. So how does a client (who is not the iRODS user) access this key? By using an executable program which is setuid to the iRODS user to read the key and generate the authenticator. This program, called genOSAuth, is installed alongside the other i-commands, and uses a key configured in at program build time. It comes from slightly different sources on the server, but it needs to match up for the authentication to succeed: - username - provided by the calling user - uid - looked up by the iRODS server using getpwnam(username) - challenge - same one as the client was sent - secret - read directly by the iRODS server (irodsAgent). Since the agent runs as the iRODS service user, it can read the file directly. If the authenticators don't match up (i.e. the client generates a different one from the server), authentication is denied. So what does each piece contribute? - username/uid - main identification of who the request is for (and who to look up in the iRODS database). Adding uid (and using OS mechanisms to look it up vs allow the client to provide it) guarantees that we're looking at the same UNIX username/uid space. - challenge - identifies a particular connection. Adding this to the authenticator means that somebody can't save an authenticator from one session and re-use it in another. One implication is that you cannot impersonate another user by telling iRODS you are that user, and re-using a previously generated valid authenticator. - secret - this is the bit that makes sure the client can't just present anybody's credential. How come? Because if the client doesn't use the genOSAuth executable that is properly installed by the system administrator, and this genOSAuth can't read the file protected by UNIX file permissions, authentication will fail. So we are guaranteed that the client must generate an authenticator using the process we've defined and put in place, so they can just make up usernames and uids (since we run getuid() on the client side to make sure they are who they say they are). None of this process or procedure needs to be obfuscated. The randomness generated by the challenge, and the OS level protection of the key file provide the security, not the process itself. With that in mind, it is important to protect the key file. This file must be owned by the user that runs the iRODS service, and this file must only be readable to that user. The file location is built into the iRODS server and genOSAuth as a static location so that this location cannot be influenced by the client. If an attacker can replace the iRODS server process (irodsAgent) and genOSAuth, with their own versions, then the system could be compromised, but that would imply that the OS itself has been compromised, meaning OS authentication couldn't be trusted anyway (since I could potentially even replace getuid()). Another potential attack point would be if the key file is kept in NFS. If NFS clients are restricted, and all clients are managed by the same organization as the one who manages the iRODS installation, then this is probably ok, but that means the contents of the file will go over the network at some point in the clear. And if somebody could have their own client mount the share with the key file, they could read and write the file at will. In many organizations, though, once one has gone through the various VPNs, firewalls and login processes, a user is considered trusted, so perhaps putting the key in a shared location is ok. How to configure OS authentication ---------------------------- 1. Build in support for OS authentication. Edit config/config.mk and un-comment OS_AUTH. You will also need to provide a full path to the shared iRODS key file. That is, change the line: #OS_AUTH = 1 to OS_AUTH = 1 and set the path of the key file (e.g. /opt/iRODS/config/irods.key) ifdef OS_AUTH OS_AUTH_KEYFILE = /opt/iRODS/config/irods.key endif 2. Run 'make' to rebuild the servers and libraries/i-commands. In addition to building the support libraries, the genOSAuth executable will be built alongside the other i-commands. 3. If you haven't done so already, generate the irods.key file. There is no format to the key file. The OS authentication library will read all bytes contained in this file. It can be random bytes, a random string, or even a human-readable password if you wish. Copy the key file into place on all the potential iRODS client and server nodes. If you have set OS_AUTH_KEYFILE to a location on a shared filesystem, this needs to be done only once, but if OS_AUTH_KEYFILE references a local (to the node) path name, they you need to copy the key (securely. e.g. with scp) to all client and server nodes. Make sure that the key file is owned by the user who runs the iRODS services, and that it is only readable by this user. If your iRODS service user is UNIX user 'irods', you would do: chown irods /opt/iRODS/config/irods.key chmod 400 /opt/iRODS/config/irods.key Now you must make the genOSAuth executable owned by the iRODS service user (if not already) and make it 'setuid' to this userid, so that when it runs, it can read the key file. Like so: chown irods /opt/iRODS/clients/i-commands/bin/genOSAuth chmod 4755 /opt/iRODS/clients/i-commands/bin/genOSAuth Note that this must be done on all iRODS clients/servers if the iRODS binaries are stored on local filesystems. If iRODS is installed in NFS, make sure that the volume containing the iRODS executables allows setuid execution. 4. Make sure that the iRODS ICAT-enabled server node "sees" the same username/uid space as the client nodes. Normally this is done by using some network identity service such as NIS, LDAP or AD (and is often configured in /etc/nsswitch.conf ... on linux anyway). 5. Add usernames to iRODS using 'iadmin mkuser'. Note that you do not need to assign a password to the user using 'iadmin moduser password', as this is ignored when using OS authentication. User environment ---------------- Users set their irodsAuthScheme variable in their .irodsEnv file (or in their environment) to 'OS' or 'os'. Users need to ensure that the genOSAuth executable is in their path. It's normally installed with the rest of the i-commands, so if the i-commands are in the path, genOSAuth should be locatable. Otherwise, make sure to set the path to include the path to genOSAuth. The user should not need to do anything further. As long as genOSAuth and the key file have been installed properly, the authentication should succeed if the user exists in iRODS and is resolvable as a UNIX username on the iRODS ICAT-enabled server.