z/OS UNIX System Services Users and Groups
Introduction
In my previous articles, I discussed file and file system security. We saw the concept of a user owner and a group owner for files and directories. In this article, I discuss what those owners are, how they are represented in UNIX, and how they are defined to RACF. I then cover some hints and tips on managing the assignment and the de-provisioning of these IDs. My next article, “UNIX Superusers”, will cover the extremely important topic of the highly privileged UNIX superuser.
UNIX users
Say you have a RACF user ID named SNEHA with a default group of EKNIGHTS. How do I make her a z/OS UNIX user? Fundamentally:
ALTUSER SNEHA OMVS(UID(1234567))
ALTGROUP EKNIGHTS OMVS(GID(7654321))
That’s it! Sneha can now enter the OMVS command from the TSO command line to enter the UNIX shell and do UNIX stuff to her heart’s content.
Note: Technically, only the user’s current connect group must have a GID. The current connect group in practice is almost always the user’s default group. However, if an application, such as TSO, allows you to specify a group in your logon dialog, then that group is your current connect group. Even so, the distinction is almost meaningless unless you are running with list-of-groups inactive (SETROPTS NOGRPLIST), and I’ll bet you a beer that you are not.
UNIX users are known to the UNIX kernel and file systems simply as a number (queue Bob Seger song here). Same with groups. This is part of the standard. But z/OS knows users as user IDs. When UNIX System Services (originally called OpenEdition) was implemented, this was resolved by adding the OMVS segment to the RACF USER and GROUP profile containing a UID and GID field, respectively, in which to assign that number. But this is no ordinary RACF profile field. It is defined as an alias field. This means that RACF and SAF interfaces can be used to quickly map the numeric value to the RACF profile containing it. In fact, there is even a VLF layer of caching on top of that (the IRRUMAP and IRRGMAP VLF classes). This is designed so that UNIX can map UIDs/GIDs at a very high frequency with as little I/O and database contention as possible. This is all so that you can continue to view and specify RACF user IDs and group names even when using shell commands and other UNIX interfaces.
Note: From here on, instead of constantly saying “UID or GID”, I will use the term “xID” unless a differentiation is necessary.
In the file security article, I showed you the following ls command output:
# ls -l
total 0
-rw-r--r-- 1 BRUCE SYS1 0 Jul 14 15:27 file1
-rw-r--r-- 1 BRUCE SYS1 0 Jul 14 15:27 file2
drwxr-xr-x 2 BRUCE SYS1 0 Jul 14 15:27 sdir1
drwxr-xr-x 2 BRUCE SYS1 0 Jul 14 15:27 sdir2
The ls command is displaying BRUCE and SYS1 using the mapping services mentioned above. To see what’s really contained as the owner in the file’s security metadata, use the -n option, which says to show the numeric values:
# ls -n
total 0
-rw-r--r-- 1 18136 1 0 Jul 14 15:27 file1
-rw-r--r-- 1 18136 1 0 Jul 14 15:27 file2
drwxr-xr-x 2 18136 1 0 Jul 14 15:27 sdir1
drwxr-xr-x 2 18136 1 0 Jul 14 15:27 sdir2
You can see the user ID BRUCE has been assigned a UID of 18136, and the SYS1 group has been assigned a GID of 1.
Bruce and Sneha are probably connected to a bunch of other groups, also. They need not be UNIX groups, but UNIX will only recognize those groups that have a GID. You can see how UNIX knows you (or another user) by issuing the id command in the shell:
# id bruce
uid=18136(BRUCE) gid=1(SYS1) groups=11(GROUP1),21(GROUP2),31(GROUP3),41(GROUP4),51(GROUP5)
Unlike user IDs and group names, which share a name space, UID values are in a separate space than GIDs. For example, you can assign a user the UID 999 and a group the GID 999, and these have no relationship to each other. The xID is a numeric value from 0 – 2,147,483,647. Apart from a UID value of 0, there is nothing special about the value. A user with a UID of 0 is considered a UNIX superuser. This is extremely important from a security perspective, and we will describe it in detail in the next article of this series, “UNIX Superusers”. A GID of 0 has no special significance. There is no such thing as a supergroup (with apologies to the Traveling Wilburys).
xID uniqueness
Users and groups should have a unique xID, but this is not enforced by default, because the standard does not require it. So, what if I also assign a UID of 18136 to Sneha? UNIX considers Sneha to be equivalent to Bruce. Sneha is treated as the file owner of any file owned by Bruce, and she has access to any file to which Bruce has access, whether by owner permission bits or acl entry. When the ls command is issued for such a file, it may display BRUCE, or it may display SNEHA. Even if you specify BRUCE, as opposed to 18136, in a chown or setfacl command, SNEHA still has the same ownership/access.
Some have characterized this as a loss of accountability, but I disagree. It’s really a loss of access control. A UNIX process’ identity is represented in a control block call the User Security Packet (USP). This is anchored (indirectly) off the user’s ACEE. When RACF creates SMF Type 80 records for various UNIX-related events, they always contain information from the ACEE, including the user ID. So if you are logging file access, and access is granted for UID 18136, you will be able to tell whether it was Bruce or Sneha who accessed that file.
But it is still extremely important to keep xIDs unique. Fortunately, RACF provides a control to do just that. By defining the SHARED.IDS profile in the UNIXPRIV class, RACF will reject any attempt to assign an xID that is already in use. Because there are always exceptions, there is a SHARED keyword that must be specified if you want to override the new default behavior. You must have system the SPECIAL attribute, or have READ access to SHARED.IDS, in order to use this keyword.
Why might you want to override the uniqueness restriction? Maybe I have another user id of BRUCE2 for some reason, and you see no need why they shouldn’t share a UID. However, the most common exception is for UID(0). It is sometimes unavoidable that a UNIX application must run as a superuser. Again, we will cover this in more detail later.
It is extremely important to note that the definition of SHARED.IDS has no effect on existing duplicate xIDs. RACF provides the UIDS and GIDS sample reports in the IRRICE member of SYS1.SAMPLIB to identify instances of shared xIDs in the RACF database. For a specific UID or GID, you can find all occurrences using the RACF SEARCH command. For example:
SEARCH CLASS(USER) UID(1234567)
SEARCH CLASS(USER) UID(0)
SEARCH CLASS(GROUP) GID(7654321)
Provisioning a user for z/OS UNIX
When provisioning a user for z/OS UNIX, there is one major issue to consider. Are you keeping them consistent per user across the entire enterprise? Or just within a sysplex?
In the former case, you probably have (or want) a centralized place where xIDs are doled out, and that may not be on z/OS.
But if you are only worried about z/OS, then RACF provides mechanisms whereby unique xID values can be automatically derived for you. These require that SHARED.IDS be defined.
The first mechanism that RACF provided was the AUTOUID and AUTOGID keywords in the OMVS segment. These use the BPX.NEXT.USER profile in the FACILITY class in whose APPLDATA field you define a starting point, or range, of values from which RACF selects candidate xID values. These are first checked to make sure they are not already in use before being assigned.
Later, a more comprehensive function was provided whereby the entire OMVS segment is automatically defined when the user performs its first action that requires z/OS UNIX, such as issuing the OMVS command from TSO. This builds on both SHARED.IDS and BPX.NEXT.USER. You activate this function by defining the BPX.UNIQUE.USER in the FACILITY class. You provide a model user ID in this profile’s APPLDATA. You then define that user ID with an OMVS segment containing values that will be copied into the OMVS segment of a new UNIX user. The HOME field (which we have not yet mentioned) in this OMVS segment can contain the special “&racuid” symbol which will be replaced with the actual user’s user ID when its OMVS segment is created. For example, specifying /u/&racuid in the model OMVS segment will result in a HOME value of /u/bruce in an OMVS segment created automatically for user ID BRUCE.
The UNIX automount facility (outside the scope of this article) can also be configured to automatically allocate a zFS aggregate, create a home directory, and mount the aggregate on this directory. That is, with no effort on the end-user’s part, the very first time they enter the OMVS command, they are fully provisioned with an OMVS segment in their RACF USER profile, and a home directory owned by them in which they can immediately start creating files!
But what about Least Privilege, attack vectors, and all those other cool security buzzwords? What if a certain user has no reason to use z/OS UNIX, and I don’t want to spend the resources to make it happen, just so they can be the target of a UNIX-initiated hack? This is a totally valid concern. Have no fear, automatic assignment can be blocked by defining an ‘empty OMVS segment’ for that user as part of its provisioning. That is:
ADDUSER BRYAN TSO(…) OMVS
If you have implemented automatic assignment of OMVS segments, you should also consider your user on-boarding procedure and incorporate the creation of an empty OMVS segment as necessary.
De-provisioning a z/OS UNIX user
When you delete a RACF user ID or group, part of this procedure should involve running the IRRRID00 utility to clean up residual references to the user in the RACF database; for example, access list entries in a general resource or DATASET profile. Imagine that John Doe with user ID JDOE leaves the company. The following year, a different John Doe is hired, with a completely different job role, and requests the user id JDOE. Had you not run IRRRID00 (or equivalent function), the new John Doe will inadvertently gain access to any resources covered by a RACF profile with the old JDOE user ID in the access list. He will also be able to modify any RACF profile whose OWNER field contains JDOE.
A similar issue exists for z/OS UNIX UIDs and GIDs. Say the old John Doe’s UID was 464646, and for whatever reason a new user (with any new user ID, not just that of JDOE) is assigned UID 464646. Guess what? The new user now owns whatever files Old John had kicking around and has access to whatever files Old John had access to via access control list entries. When a z/OS UNIX user is deleted, you should also de-provision his personal zFS file system. But that may not be enough. You should also make sure 464646 doesn’t own other files and is not permitted to other files.
IRRRID00 only works against the RACF database, so it doesn’t help here. However, the shell ‘find’ command comes to the rescue again. For example,
find / -user jdoe
will find files owned by JDOE.
Or, if JDOE had already been deleted, but you know his UID was 464646:
find / -user 464646
To find acl occurrences:
find / -acl_user jdoe
find / -acl_user 464646
Similarly, for groups:
find / -group secadmns
find / -group 353535
find / -acl_group secadmns
find / -acl_group 353535
Or, if at any time you want to find xID references that don’t map to a RACF profile:
find / -nouser
find / -nogroup
find / -acl_nouser
find / -acl_nogroup
Recall that in my article about file system security, I mentioned the “HFS unload” (irrhfsu) download. If you prefer, you can run queries against its output to discover the same information!
Conclusion
What are some things you can do, right now, regarding UNIX UIDs and GIDs:
- Make sure you’ve defined SHARED.IDS in the UNIXPRIV class.
- Check the file system for the references to UIDs that don’t map to user IDs and GIDs that don’t map to groups.
- Check for occurrences of multiply assigned xIDs.
- Check your user on-boarding and off-boarding procedures to make sure xIDs are accounted for.
- Check if your on-boarding procedures block automatic xID and OMVS segment assignment for users with no need to use UNIX.
Brought to you by Bruce Wells
Bruce Wells is the RACF Product Owner, and has been a RACF design and developer on both the z/VM and z/OS versions for over 30 years.