Page Body

Managing User and Group Accounts on GNU/Linux

Managing accounts on your GNU/Linux system is a fundamental part of system administration.

Note: If you are not familiar with the GNU/Linux command line interface, review the Conventions page before proceeding.

User and Group IDs

A user is an entity that needs access to system resources. All GNU/Linux users are assigned a unique user ID (UID), which is an integer.

GNU/Linux uses groups for organizing users. Groups are collections of user accounts with shared permissions. By default, every user belongs to a default group (i.e., their primary group). When a user logs in, their group membership is set to their primary group.

A user's UID is the same as their primary group's unique group ID (GID). It is possible for multiple users to have the same UID, but different account passwords. However, this is usually not a good idea and is not recommended.

Only the root user can add or remove users and groups.

User Account Types

GNU/Linux has four types of accounts:

  1. root
  2. System
  3. Normal
  4. Network

Specific UID ranges or values are associated with certain types of user accounts:

1-999
System users. These users do not map to actual people, but are used as security identities for system daemons to implement privilege separation and run system daemons with minimal privileges.
0-99
Statically allocated system user accounts.
100-499
System user accounts dynamically allocated by system administrators and post-installation scripts.
1000-65533 and 65536-4294967294
Normal users. Accounts mapped to people.
1000-1499
System administrators and server operators. This is not required, but may be done for organizational purposes.
10000-65533
Network accounts. This is not required, but may be done for organizational purposes.
0
root user (the superuser).
1 or 2
bin user.
48
apache user.
65534
nobody user. This account is used for many things (e.g., anonymous access on FTP/HTTP servers), but does not have write access on a system.
65534 is also referred to as the overflow UID. This is where various subsystems map unmappable users to (e.g., file systems only supporting 16-bit UIDs, the Network File System (NFS), or user namespacing).

Pseudo-user accounts belong to certain software systems (e.g., postfix for the Postfix mail server) or certain devices (e.g., printers). You can access these accounts like other user accounts via the su command. These accounts are helpful as file or directory owners, in order to fit the access rights tied to file ownership to special requirements without having to use the root account. The same logic applies to groups.

As with UID values, specific GID values are associated with certain types of group accounts:

1-999
System groups. These groups do not map to actual people, but are used as security identities for system daemons to implement privilege separation and run system daemons with minimal privileges.
0-99
Statically allocated system group accounts.
100-499
System group accounts dynamically allocated by system administrators and post installation scripts.
1000-65533 and 65536-4294967294
Normal groups. Accounts mapped to people.
1000-1499
System administrators and server operators. This is not required, but may be done for organizational purposes.
10000-65533
Network accounts. This is not required, but may be done for organizational purposes.
0
root group (the superuser group).
1 or 2
bin group.
50
staff group.
100
users group. This is where you can place regular users and give them access to resources by assigning it (i.e., the users group) group ownership of things that all users should have access to.

The root user's privileges are tied to UID 0. GID 0 does not confer any additional access privileges. Administrative groups (e.g., root, bin) are similar to the system's pseudo-user accounts. Many files are assigned to groups like this.

User and Group Accounts

There are several files on a GNU/Linux system that pertain to users and groups.

/etc/passwd

Each user on a GNU/Linux system has a corresponding line in the /etc/passwd file. The file can be viewed by running the following command:

$ less '/etc/passwd' | head
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

The file consists of lines made from the following colon-delimited fields:

  1. ex_login_name
  2. Optional ex_encrypted_password
  3. ex_UID
  4. ex_GID
  5. ex_GECOS_information
  6. ex_user_home_directory
  7. Optional ex_user_login_shell

Usernames should be 8 characters or less to ensure compatibility in heterogeneous environments (e.g., UNIX systems limit usernames to 8 characters).

There are several possible scenarios for the optional password field:

  • If the password field is blank, no password is required to authenticate the specified login name. However, some applications that read /etc/passwd may decide to not permit any access if the field is not filled.
  • If the password is an x, the encrypted password is stored in the user's corresponding line in the /etc/shadow file.
  • If the password field is any other string, it is treated as an encrypted password, as specified by crypt(3).

On GNU/Linux systems, setting the password field to an asterisk (*) is a common way to disable direct logins to an account, while still preserving its name. An alternative possible password value is *NP*, which indicates to use a Network Information Service (NIS) server to obtain the password.

Every user must belong to at least one group, i.e., their primary group.

vipw

/etc/passwd can be edited with the vipw command:

# vipw

General Electric Comprehensive Operating Supervisor/System (GECOS)

The General Electric Comprehensive Operating Supervisor/System (GECOS) field is used to record general information about an account or its user. Often, this field is used to store the user's real name.

finger

GECOS information for the current user can be viewed with the finger command (likely, you will need to install this program from your distribution's repository, e.g., # apt install finger, # dnf install finger). GECOS information for a specific user(s) can be viewed by providing their login name(s) to the finger command as an argument.

finger ex_login_name...

chfn

To change the GECOS information for the current user, use the chfn command. If you have root privileges, you can change the GECOS information for another user by passing their username (login name) to chfn as an argument:

# chfn ex_login_name

/etc/shadow

The x value for a password in a /etc/passwd line is a place holder for the user's password, which is actually stored in encrypted form in the /etc/shadow file. /etc/shadow can be viewed by running:

# less '/etc/shadow' | head
root:*:18827:0:99999:7:::
daemon:*:18820:0:99999:7:::
bin:*:18820:0:99999:7:::
sys:*:18820:0:99999:7:::
sync:*:18820:0:99999:7:::
games:*:18820:0:99999:7:::
man:*:18820:0:99999:7:::
lp:*:18820:0:99999:7:::
mail:*:18820:0:99999:7:::
news:*:18820:0:99999:7:::

The file consists of lines made from the following colon-delimited fields:

  1. ex_login_name
  2. ex_encrypted_password
  3. ex_date_of_last_password_change
  4. ex_minimum_password_age
  5. ex_maximum_password_age
  6. ex_password_warning_period
  7. ex_password_inactivity_period
  8. ex_account_expiration_date

The ex_login_name field corresponds to a line in /etc/passwd. This field joins the two files.

There are several possible scenarios for the password field:

  • If the password field contains a string that is not a valid result of crypt(3) (e.g., ! or *), the password will be locked and the user will not be able to log in with a password, but other authentication methods (e.g., SSH key authentication) are still allowed. The remaining characters on the line represent the password field before the password was locked.
  • If the password field is blank, no password is required to authenticate the specified login name. However, some applications that read /etc/shadow may decide to not permit any access if the field is not filled.

Only the root user can read and write to the /etc/shadow file. Only members of the shadow group can read it.

Fields 3 through 8 in each line describe various aspects and policies for that user's account and password.

date of last password change
The days since the UNIX Epoch time (January 1, 1970) that have elapsed since the password was last changed.
A value of 0 has a special meaning and indicates that the user should change their password the next time that they log in.
An empty field means that password aging features are disabled.
minimum password age
The days that must elapse before the password can be changed.
maximum password age
The days before the password must be changed.
An empty field indicates that there are no maximum password age, no password warning period, and no password inactivity period.
If the maximum password age is less than the minimum password age, the user cannot change their password.
password warning period
The days before the password expires during which the user will be warned.
Both an empty field and value 0 mean that there is no password warning period.
password inactivity period
The number of days after the password expires in which the user could still log in if their password is changed during login.
After both expiration of the password and the elapsing of this period, the password is no longer valid and logging in with it is not possible.
An empty field indicates that there is no enforcement of an inactivity period.
account expiration date
The number of days from the UNIX Epoch time, and the day the account will expire and be disabled.
Account expiration is distinct from password expiration. After account expiration, the user is not allowed to log in. After password expiration, the user is not allowed to log in with their password, unless they are within a password inactivity period, where they will be allowed to change their password upon login.

The last field in the /etc/shadow file is reserved for future use.

Keep in mind, the field's above are respected by the text console login process. They are not necessarily respected by other parts of the system, including the graphical login screen.

The /etc/shadow file can be edited by using the vipw command's -s option:

# vipw -s

pwck, pwconv, and pwunconv

The pwck command verifies the integrity of password files by confirming that the /etc/passwd and /etc/shadow files are in sync:

# pwck

If the files are not in sync, there are two commands that can be used to resolve the incongruity:

  1. pwconv creates missing /etc/shadow users from /etc/passwd (# pwconv).
  2. pwunconv creates missing /etc/passwd users from /etc/shadow (# pwunconv).

/etc/group, newgrp, and gpasswd

Each group on a GNU/Linux has a corresponding line in the /etc/group file. The file can be viewed by running the following command:

$ less '/etc/group' | head
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:amnesia
mail:x:8:
news:x:9:

The file consists of lines made from the following colon-delimited fields:

  • ex_group_name
  • Optional ex_encrypted_password
  • ex_GID
  • Optional ex_user_list

The optional password field is for an optional group password that lets users that are not a member of the group assume group membership using the newgrp command:

  • If the password field is blank, no password is needed to assume the group's membership with the newgrp command.
  • If the password is an x, the encrypted password is stored in the group's corresponding line in the /etc/gshadow file.
  • A * in the optional password field prevents normal users from changing to this group with the newgrp command.

If a user is a member of a group that has been assigned a password, they do not need to enter the password when using the newgrp command with that group.

A group password is assigned through the gpasswd command:

# gpasswd ex_group

If you do not have root access, but you are a group administrator, you can assign/re-assign a password to that group using gpasswd, as well.

The /etc/group ex_user_list field is a comma-separated list of usernames. Usually, users are not listed in the entry of their primary group in this file.

vigr

/etc/group can be edited with the vigr command:

# vigr

/etc/gshadow

The x value for a password in a /etc/group line is a place holder for the group's password, which is actually stored in encrypted form in the /etc/gshadow file. The /etc/gshadow file can be viewed by running:

# less '/etc/gshadow' | head
root:*::
daemon:*::
bin:*::
sys:*::
adm:*::
tty:*::
disk:*::
lp:*::amnesia
mail:*::
news:*::

The file consists of lines made from the following colon-delimited fields:

  • ex_group_name
  • ex_encrypted_password
  • ex_administrators
  • ex_members

The ex_group_name field corresponds to a line in /etc/group. This field joins the two files.

There are several possible scenarios for the password field:

  • If the password field contains a string that is not a valid result of crypt(3) (e.g., ! or *), the password will be locked and users will not be able to use a password to access the group (group members do not need the password). The remaining characters on the line represent the password field before the password was locked.
  • If the password field is blank, then only group members can gain the group permissions.

Users listed in the ex_administrators field are group administrators that are able to add or remove members of the group, and change the group's password. Group administrators also have the same group permissions as group members.

The /etc/gshadow file can be edited by using the vigr command's -s option:

# vigr -s

grpck, grpconv, and grpunconv

The grpck command verifies the integrity of group files by confirming that the /etc/group and /etc/gshadow files are in sync:

# grpck

If the files are not in sync, there are two commands that can be used to resolve the incongruity:

  1. grpconv creates missing /etc/gshadow groups from /etc/group (# grpconv).
  2. grpunconv creates missing /etc/group groups from /etc/gshadow (# grpunconv).

Displaying Database Information With getent

The getent command displays entries from databases supported by the Name Service Switch libraries, which are configured in /etc/nsswitch.conf.

getent ex_database

This command can be used to display the information stored in the previously mentioned user and group files. ex_database is the database name associated with these files. The accepted database name values are listed in /etc/nsswitch.conf (e.g., passwd, shadow. group, or gshadow). Accessing some of these databases will require root access.

Here, database means the totality of all sources from where the C library can obtain information on that topic. Databases are searched in the order determined by the /etc/nsswitch.conf file.

getent can be provided one or more keys (e.g., a username) as arguments to show only information related to that key(s).

getent ex_database ex_key...

Setting and Updating User Account Passwords With passwd

The passwd command is used to change the current user's password. It is also the command that sets the values for what you see regarding a user in /etc/shadow.

Helpful options include:

-d, --delete
Delete a user's password (i.e., make it empty).
If the password field is blank, no password is required to authenticate the specified login name. However, some applications that read /etc/shadow may decide to not permit any access if the field is not filled.
-i ex_inactive_days, --inactive ex_inactive_days
Set the number of days an account with an expired password can be inactive before it is disabled (i.e., the password inactivity period).
-l ex_login_name, --lock ex_login_name
Lock the password of the named account.
This option adds a ! to the beginning of the password. The user will not be able to log in with a password, but other authentication methods (e.g., SSH key authentication) are still allowed.
-n ex_min_days, --mindays ex_min_days
Set the minimum password lifetime in days (i.e., the minimum password age).
A value of 0 means that the user can change their password at any time.
-S, --status
Display account status information (e.g., username, whether account has a locked password (L), has no password (NP), or a usable password (P), date of last password change (date of last password change), minimum password age, maximum password age, password warning period, password inactivity period).
-u ex_login_name, --unlock ex_login_name
Unlock the password of the named account.
-w ex_warning_days, --warndays ex_warning_days
Set the number of warning days before the password expires (i.e., the password warning period).
-x ex_max_days, --maxdays ex_max_days
Sets the maximum password lifetime in days (i.e., the maximum password age). After ex_max_days, the password must be changed.

If you have root access, you can change the password for a different user account by providing their username as an argument to passwd:

# passwd ex_login_name

Updating Passwords For Multiple Existing Users With chpasswd

chpasswd is an interactive command that updates passwords for existing users in batch mode. It reads a list of username and password pairs from the standard input and uses this information to update a group of existing users.

# chpasswd

Each username/password pair is given per line in the following format:

username:password

By default, passwords must be supplied in clear-text, and are subsequently encrypted by chpasswd.

After you are done entering username/password pairs, enter Ctrl+d to exit.

Alternatively, a file with username/password pairs (one per line) can be passed to chpasswd:

# chpasswd < ex_file.txt

Changing Password Expiry Information With chage

The chage command is another command (aside from passwd) that can be used to change users' password expiry information in /etc/shadow.

# chage ex_login_name

After invoking chage without any options, you are presented with a sequence of current expiry information values to change or confirm.

Useful options include:

-d ex_last_days, --lastday ex_last_days
Set the number of days since the UNIX Epoch time that the password was last changed (i.e., the date of last password change). A date in the format of YYYY-MM-DD may also be used in place of ex_last_days.
-E ex_expire_date, --expiredate ex_expire_date
Set the number of days since the UNIX Epoch time, and the date on which the user's account will be disabled (i.e., the account expiration date). The format is either an integer number of days or the date in the format YYYY-MM-DD.
Passing the number -1 as ex_expire_date will remove an account expiration date.
-I ex_inactive_days, --inactive ex_inactive_days
Set the number of days of inactivity (i.e., no logins) after a password has expired before the user account is locked (i.e., the password inactivity period).
Passing the number -1 as ex_expire_date will remove an account's inactivity.
-l ex_login_name, --list ex_login_name
Show account aging information.
-m ex_min_days, --mindays ex_min_days
Set the minimum number of days that the user must wait until they can change their password (i.e., the minimum password age). A value of 0 for ex_min_days means that the user can change their password at any time.
-M ex_max_days, --maxdays ex_max_days
Set the maximum number of days that can go by before the user must change their password (i.e., the maximum password age).
A value of -1 as ex_max_days will remove checking a password's validity.
-W ex_warn_days, --warndays ex_warn_days
Set the number of warning days before a password change in required (i.e., the password warning period).

Disabling and Enabling User Accounts

The chage command can be used to disable or enable a user account via its -E (--expiredate) option.

To disable a user account, set its ex_expire_date to 0:

# chage -E 1 ex_login_name

To enable a user account, set its ex_expire_date to -1:

# chage -E -1 ex_login_name

Locking and Unlocking User Passwords

Both the passwd and usermod commands can be used to lock and unlock user passwords (i.e., to prevent a user from logging into a system with their password).

A user password can be locked like so:

# passwd -l ex_login_name

Or:

# usermod -L ex_login_name

A user account can be unlocked by running one of the following commands:

# passwd -u ex_login_name

Or:

# usermod -U ex_login_name

Adding User Accounts With useradd

The useradd command creates new user accounts and updates default new user information.

# useradd ex_login_name

This command uses the /etc/default/useradd and /etc/login.defs files as input.

Useful options include:

-b ex_base_directory, --base-dir ex_base_directory
Specify the system's base directory if -d ex_home_directory is not specified. ex_base_directory is concatenanted with the ex_login_name to define the home directory.
-c ex_comment, --comment ex_comment
Any text string. Generally, this is a short description of the login and is currently used as the field for the user's full name (GECOS).
-d ex_home_directory, --home-dir ex_home_directory
Specify the home directory. ex_home_directory does not have to exist, but will not be created if it is missing.
-D, --defaults
Display the defaults defined in /etc/default/useradd. Can be used to modify defaults when used in conjunction with the -b, -e, -f, -g, and -s options.
-e ex_expire_date, --expiredate ex_expire_date
Set an expiration date on the account, after which it is disabled (i.e., the account expiration date). The date is specified in the format of YYYY-MM-DD.
-f ex_inactive_days, --inactive ex_inactive_days
Specify the number of days after the password has expired in which the user can still log in (if their password is changed during login) before their account is disabled (i.e., the password inactivity period).
-g ex_group, --gid ex_group
Specify primary group. Either a GID or group name can be used. ex_group must exist.
-G ex_secondary_group..., --groups ex_secondary_group...
Set secondary group membership. Is either a single value or a list of comma-separated values of groups (e.g., ex_secondary_group_1,ex_secondary_group_2) that the user is to be a secondary member of.
-k ex_skeleton_directory, --skel ex_skeleton_directory
Specify skeleton directory. This option is only valid if the -m option is specified.
The skeleton directory contains the files and directories to be copied to the user's home directory when the directory is created by useradd. If this option is not set, the skeleton directory is defined by the SKEL variable in /etc/default/useradd or, by default, in /etc/skel.
-m, --create-home
Create user's home directory if it does not exist.
The files and directories contained in the skeleton directory will be copied to the home directory. By default, if this option is not specified and CREATE_HOME is not enabled, no home directories are created.
-o, --non-unique
Allow creation of a user with a non-unique UID. This option is only valid in combination with the -u option.
-s ex_shell, --shell ex_shell
Specify the full path of the filename of the user's login shell.
-u ex_uid, --uid ex_uid
Specify UID. This UID must be unique, unless the -o option is also used.

After a user is created, their account password is considered locked until it is set. You can set the account password using the previously mentioned passwd command:

# passwd ex_login_name

Creating and Updating Multiple User Accounts With newusers

newusers is an interactive command that creates new users in batch mode. It reads user information from the standard input and uses this information to create new users.

# newusers

Each user is provided per line with the following colon-delimited fields:

  1. ex_login_name
  2. ex_clear_text_password
  3. ex_UID
  4. ex_GID
  5. ex_GECOS_info
  6. ex_user_home_directory
  7. ex_user_login_shell

By default, passwords are supplied in clear-text and are encrypted by newusers.

After you are done entering new users, press Ctrl+d to exit.

Alternatively, a file with new user entries (one per line) can be passed to the newusers command:

# newusers < ex_file.txt

Aside from creating new users, the newusers command can be used to update information for existing users, as well.

Adding Groups With groupadd

The groupadd command creates a new group using the values specified on the command line and the default values from the system.

# groupadd ex_group

A group with a specific GID can be created through the use of the -g (--gid) option:

# groupadd -g ex_gid ex_group

Modifying a User Account With usermod

The usermod command modifies user accounts:

# usermod ex_login_name

Substantive options include:

-c ex_comment, --comment ex_comment
The new value of the user's password file comment field. Modifies GECO field in /etc/passwd.
-d ex_home_directory, --home ex_home_directory
The user's new home directory. Changing a user's home directory does not change user ownership of files in the new or old home directory.
-e ex_expire_date, --expiredate ex_expire_date
The date on which the user account will be disabled (i.e., the account expiration date). The date is specified in the YYYY-MM-DD format.
An empty ex_expire_date will disable the expiration of the account.
-f ex_inactive_days, --inactive ex_inactive_days
The number of days after a password expires until the password is locked (i.e., the password inactivity period).
An ex_inactive_days value of 0 locks the password as soon as it expires and a value of -1 disables the feature.
-g ex_group, --gid ex_group
The group name or GID of the user's new primary group. The group must exist.
Any object from the user's home directory owned by the previous primary group of the user will be owned by this new group.
Group ownership of files outside of the user's home directory must be manually fixed.
-G ex_group..., --groups ex_group...
A list of secondary groups that the user is also a member of. Each group is separated from the next by a comma, with no intervening white space (e.g., ex_group_1,ex_group_2).
ex_group is a single value or a list of comma-separated values of groups that the user is to be a secondary member of. This overwrites any current secondary group memberships (i.e., if a user is a member of a group that is not specified with this option, they will be removed from the group). This behavior can be changed with the addition of the -a (--append) option, which adds the user to the secondary group(s).
-l ex_new_login, --login ex_new_login
The name of the user that will be changed from ex_login to ex_new_login. Nothing else is changed. The user's home directory or mail spool should likely be manually renamed to reflect the new login name.
-L, --lock
Locks a user's password (which prevents the user from logging into the system with a password). This adds a lock to the user's account by adding an exclamation point (!) to the front of the encrypted password in the /etc/shadow file.
-m, --move-home
Move the content of the user's home directory to the new location.
This option is only valid in combination with the -d option.
-s ex_shell, --shell ex_shell
The name of the user's new login shell. Short for --shell. Changes the path to the user's login shell. Setting ex_shell to blank causes the system to select the default login shell.
-u ex_uid, --uid ex_uid
The new UID for the user.
The user's mailbox, and any files that the user owns and that are located in the user's home directory, will have the file UID automatically changed.
The ownership of files outside of the user's home directory must be manually fixed.
-U, --unlock
Unlock a user's password. Removes the lock on the user's password by removing the exclamation point (!) from the front of the encrypted password in the /etc/shadow file.

Add an Existing User to an Existing Group

usermod can be used to add an existing user to an existing group:

# usermod -aG ex_group_name... ex_login_name

usermod's -a option is short for --append.

An alternative to the above command is to use the gpasswd command:

# gpasswd -a ex_login_name ex_group_name

gpasswd's -a option is short for --add.

Remove an Existing User From an Existing Group

usermod can used to remove an existing user from an existing group:

# usermod -G ex_group... ex_login_name

Above, ex_group... represents the group or groups that you want ex_login_name to be a member of (i.e., you would leave off the group(s) that you want to remove the user from).

An alternative to the above command is to use the gpasswd command:

# gpasswd -d ex_login_name ex_group_name

Here, ex_group_name represents the group that you want to remove ex_login_name from. -d is short for --delete.

Set Group Administrators

The gpasswd command can be used to define a group's administrator:

# gpasswd -A ex_login_name... ex_group_name

-A is short for --administrators and ex_login_name can be a comma-separated list of usernames (e.g., ex_login_name_1,ex_login_name_2).

Modifying Groups

A group's name and GID can be modified with the groupmod command.

To change the group's name, use the -n (--new-name) option:

# groupmod -n ex_new_group_name ex_group_name

To change the group's GID, use the -g (--gid) option:

# groupmod -g ex_new_GID ex_group_name

Objects previously group owned by the old GID tied to ex_group_name will no longer have a group name associated with their group owner's GID. You will just see the old GID as the group owner for these file system objects.

Removing Users

The userdel command deletes a user account, while retaining that user's home directory.

# userdel ex_login_name

If a user is currently logged in and you need to delete their account, you can lock their account first (# passwd -l ex_login_name or # usermod -L ex_login_name) and then kill their login shell (# killall -u ex_login_name) before you run the userdel command.

To remove a a user's home directory and mail spool (which is defined by the MAIL_DIR variable in the /etc/login.defs file), as well as their user account, add the -r (--remove) option to userdel:

# userdel -r ex_login_name

Other files that belong to the user (e.g., their crontab file) will remain and need to be manually deleted. A quick way to do this is with the find command:

# find '/' -uid ex_uid -delete

Removing Groups

The groupdel command deletes a group.

# groupdel ex_group_name

The primary group for a user may not be removed until the user's account is deleted first.

Before removing a group, there are several checks you should do:

  • Confirm that the group has no secondary members (e.g., getent group ex_group_name).
  • Confirm that the group is not a primary group for any user account (e.g., less '/etc/passwd' | grep ex_group_name).
  • Identify all objects owned by the group and change group ownership to another group (e.g., # chown -R --from=:old_gid :new_group_owner_name / or # find / -group ex_old_group_name -exec sudo chgrp new_group_owner_name '{}' \;).

Substituting User Accounts

There are several commands that can be used to substitute (switch) user accounts on a GNU/Linux system. These commands can be used to switch to any user account, but they are often used to gain access to the root user.

root privileges are required to perform operations like:

  • Creating, removing and managing accounts
  • Managing software packages
  • Removing or modifying system files
  • Restarting system services

su

By default, the su (substitute user) command substitutes your user session with that of the root user. After authenticating as the root user, you are provided with a non-login, interactive shell for the root user.

When employing the su command, it is considered best practice to specify the full path to the command (for a Debian system, su is located inside of /usr/bin/):

/usr/usr/bin/su

From this point on, from the system's point of view, you are indistinguishable from the root user. You are the root user.

If you want a login shell for the root user, you can use su's -l (--login) option:

/usr/bin/su -l

It is recommended to always use the su command with the -l option, as it avoids side effects caused by mixed environments.

If you provide su with a specific username as an argument, you can substitute your user session for that user, instead of the root user.

/usr/bin/su -l ex_login_name

You will need to know ex_login_name's password, unless you are calling su as the root user.

The su command can be used to simply run a separate command as a different user. This can be accomplished by also passing that command (and any of its arguments) to the su command's -c (--command) option:

su ex_login_name -c ex_command

The following example prints out a hello message to the standard output as the amnesia user:

# su amnesia -c 'echo Hello, world!'
Hello, world!

sudo

A alternative way to substitute user sessions on a GNU/Linux system is to utilize the sudo (substitute user do) program. sudo allows permitted users to execute a command as the root user (or another user), as specified by the system's security policy.

Your user's Real User Identifier (RUID) is used to determine the login name with which to query the security policy. Since the system is keeping track of which actual user is employing the sudo command, a log can be maintained for auditing purposes.

sudo differs from the su command in several important ways:

  • Depending on how it is configured, sudo can ask for either the root user's password or the password of the user using the sudo command (i.e., the sudoer) when they invoke sudo (the latter is preferable, as it prevents sudoers from having to know and frequently enter the root user's password).
  • A correctly entered password is retained for 15 minutes (this time period is configurable), for convenience. However, you can manually expire the cached password by running sudo -k (-k is short for --reset-timestamp). In general, sudo has more features and allows for more customization than su.
  • All commands executed via sudo are logged using the system's logging mechanism. Failures to use sudo will appear in the /var/log/auth.log file for Debian and in /var/log/messages and/or /var/log/secure file on Fedora. A typical entry will include:

    • Calling username
    • Terminal information
    • Working directory where command was executed
    • User account invoked
    • Command used, with arguments

    A sudo entry in a log looks something like Jun 10 09:50:38 tails sudo: amnesia : TTY=pts/2 ; PWD=/home/amnesia ; USER=root ; COMMAND=/usr/bin/passwd.

You can grant a user the ability to use the sudo command in at least three ways:

  1. Create an entry for the user in the /etc/sudoers file.
  2. Create a file in the /etc/sudoers.d/ directory with the user's username as the filename. Then, create an entry inside this file for the user. The permissions for this file should be 440.
  3. Create an entry for the sudo group in the /etc/sudoers file and add the user to this group.

Some GNU/Linux distributions (e.g., Debian, Ubuntu) extend sudo privileges to the first user account created during installation and completely disable log-ins to the root user account. This prevents naive users from working as the root user all of the time.

/etc/sudoers

The /etc/sudoers file controls the users that are allowed to use the sudo command and for what purposes. This is what a /etc/sudoers file looks like on a basic Debian installation:

#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults    env_reset
Defaults    mail_badpass
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d

The %sudo ALL=(ALL:ALL) ALL line is what allows members of the sudo group to execute any command. The percentage sign (%) indicates that this a group definition, versus the root ALL=(ALL:ALL) ALL line which is a user definition.

The %sudo ALL=(ALL:ALL) ALL line can broken down like so:

%sudo
The name of the group. Some GNU/Linux distributions, like Fedora, use a %wheel group, instead (e.g., %wheel ALL=(ALL) ALL).
ALL=
The hosts on the network that the rule applies to (in this case, all hosts).
(ALL:ALL)
Specifies which users and groups the members of this group can run commands as. Here, all users and all groups are covered.
ALL
Specifies which commands can be run by members of this group. For this example, all commands are included here.

The %sudo ALL=(ALL:ALL) ALL line's syntax can be generalized as follows:

who where=(as user:as group) what

Or:

user host=(run as) command

For example, here is a /etc/sudoers entry for the amnesia user:

amnesia ALL=(ALL) ALL

Wherever a login name is expected, you may specify a group too. Prefix the group's name with a percent sign to indicate that it is a group, as we saw for the sudo group above (e.g., %operators ALL=/usr/local/bin/do-backup).

By default, sudo runs all commands as root, but you can also specify another user. For example, with amnesia ALL=(mysql) /usr/bin/mysqladmin, amnesia can run the mysqladmin command as the mysql user. To do so, the amnesia user must run a command like sudo -u mysql mysqladmin flush-privileges.

When you only specify a command (without parameters), arbitrary parameters are allowed:

amnesia ALL=/usr/bin/cancel.

When no parameters should be allowed, the only parameter specified in the sudoers file must be an empty string amnesia ALL=/usr/bin/passwd ''.

In this case, amnesia would only be allowed to change the password of the root user when using passwd with the sudo command.

Be careful about commands like vi that allow users to execute shell commands. These commands are also executed with root privileges. To prevent this, you could add a rule like amnesia ALL= NOEXEC: /usr/bin/vi. This line stops vi from running child processes.

You can also specify multiple commands:

amnesia ALL=/usr/bin/cancel [a-z]+,/usr/bin/cupsenable [a-z]+

The above command allows sudo cancel, as well as sudo cupsenable, both with (at least) one parameter.

When you specify a directory name (as an absolute pathname with a trailing slash), this stands for all executable files in that directory (but not subdirectories), e.g., amnesia ALL=/usr/bin/.

A nice feature of sudo is the -e (--edit) or sudoedit command. These commands create a temporary copy of the file to be edited and then pass that copy to your default editor. Afterwards, it checks whether the copy has been changed, compared to the original, and if so, the copy replaces the original file.

This method has convenient advantages, like the fact that the editor only runs with the ordinary user's privileges so that they cannot spawn a root shell from the editor. Incidentally, the /etc/sudoers file is evaluated by sudoedit when it decides whether a user gets to use this feature or not.

/etc/sudoers supports many options that control the function of sudo. Run man 8 sudo and man 5 sudoers for more information.

visudo

Changes can be made to the /etc/sudoers file with your system's default editor by using the visudo command (visudo checks the VISUAL environment variable first, then the EDITOR environment variable, and finally the editor setting in /etc/sudoers before falling back to vi):

# visudo

visudo ensures that only one user is editing /etc/sudoers at a time and performs a syntax check immediately after the file is saved (and before putting your new configuration into effect). This is important because, in case of an error, you do not want to end up with a configuration file that will break sudo. A manual check of /etc/sudoers can be done at any time by running the # visudo -c (-c is short for --check) command.

For example, if you have a user that you want to give the ability to install software on a Fedora system, but you do not want to give them the full access that comes with adding them to the wheel group, you can use visudo to add the following line to the /etc/sudoers file:

ex_login_name ALL=/usr/bin/dnf

The above line will enable ex_login_name to utilize the /usr/bin/dnf command on all network hosts via the sudo command (e.g., sudo dnf install ex_program). Additional commands can be specified by separating them with commas (e.g., /usr/bin/dnf,/usr/sbin/shutdown).

sudoer Aliases

If you have several user accounts that you want to grant the same sudoer permissions, you can add them to a user alias.

User_Alias ex_alias = ex_users

ex_users is a comma-separated list of users. For example:

# Installer user alias definition
User_Alias INSTALLERS = amnesia,esnowden,wbinney

# INSTALLERS permissions definition
INSTALLERS ALL=/usr/bin/dnf

Above, we used the User_Alias keyword to create an INSTALLERS user alias in the /etc/sudoers file and have added three users to it. Then, we defined the permissions associated with this new INSTALLERS alias with the INSTALLERS ALL=/usr/bin/dnf line.

Aliases can be set for hosts (Host_Alias) and commands (Cmnd_Alias), as well.

Use Host_Alias to specify what systems the users can run the commands on. The following is a host alias for a network's file servers:

Host_Alias FILESERVERS = fs_1,fs_2

Use Cmnd_Alias to define an alias that contains the commands (using the full path) that you want the user you just defined to be able to run. Separate multiple commands with commas.

This is a command alias used to group storage-related commands:

Cmnd_Alias KILLPROCS = /bin/kill,/usr/bin/killall

Command aliases can be mixed with literal commands in the same rule:

amnesia ALL=PRINTING,/usr/bin/accept [a-z]+

A leading ! character can be used to exclude commands that would otherwise be allowed by a configuration:

amnesia ALL=/usr/bin/passwd [a-z]+,!/usr/bin/passwd root

Different kinds of aliases can be combined:

INSTALLERS FILESERVERS=(root) KILLPROCS

Defaults

Previously, we mentioned that you can manually expire a cached password by running sudo -k. This behavior can be changed in /etc/sudoers by use of the Defaults keyword.

For example, the following line sets the timeout to 0 (i.e., password caching is disabled):

Defaults timestamp_timeout=0

Using sudo

To start a non-login, interactive shell for the root user, you can use sudo's -s (--shell) option:

sudo -s

Unlike when using the su command, when changing to the root user with sudo, you are not asked for the root user's password. You are asked for the sudoer's password, i.e., your user account's password. This is advantageous, since it isolates permissions between multiple sudoers.

If you want a login shell for the root user, you can use sudo's -i (--login) option:

sudo -i

If you provide sudo's -u (--user=) option with a specific username as an argument, you can switch to that user's account, instead of the root user:

sudo -i -u ex_login_name

Often, sudo is used to run a command as a different user (usually the root user) via a non-login shell. This can be done by appending the command to the sudo command. If a specific user is not specified, the root user is assumed:

sudo ex_command

To run a command as a user other than the root user via a non-login shell, pass the username in question to sudo's -u option:

sudo -u ex_login_name ex_command

The following example prints out a hello message to the standard output as the amnesia user:

sudo -u amnesia echo Hello, world!
Hello, world!

Miscellaneous User and Group Commands

whoami

The whoami command prints the effective UID to the standard output.

$ whoami
amnesia

The command is essentially displaying the content of the LOGNAME or USER shell variables.

groups

The groups command prints the group membership for the current user.

$ groups
amnesia lp dialout cdrom floppy video plugdev netdev lpadmin scanner vboxsf

This command can take one or more login names to show group affiliations for that user(s).

id

The id command prints the real and effective user and group IDs for the current user. Specifically, this output includes the current user's:

  • UID
  • Primary group GID
  • Group affiliations (including each group's GID)
$ id
uid=1000(amnesia) gid=1000(amnesia) groups=1000(amnesia),7(lp),20(dialout),24(cdrom),25(floppy),44(video),46(plugdev),109(netdev),115(lpadmin),116(scanner),119(vboxsf)

You can provide this command a specific login name as an argument to view the information associated with that user.

The -u (--user), -g (--group), and -G (--groups) options can be used to show just the UID, primary group GID, or all group GIDS, respectively. These options are mutually exclusive.

Also, if you add the -n (--name) option to the -u, -g, or -G options, you will see the corresponding name, instead of the numerical UID/GID.

$ id -Gn
amnesia lp dialout cdrom floppy video plugdev netdev lpadmin scanner vboxsf

Essentially, the id -Gn command above is equivalent to the groups command.

who

The who command prints information about users that are logged on to the system to the standard output.

$ who
amnesia  :1           2020-08-04 22:43 (:1)

w

Like the who command, the w command prints information about users that are logged in, but also displays what they are doing and the system load averages. Specifically, the header includes:

  • The current time
  • How long the system has been running
  • How many users are currently logged on
  • The system load averages for the past 1, 5, and 15 minutes
$ w
 22:44:19 up 1 min,  1 user,  load average: 1.54, 0.86, 0.33
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
amnesia  :1       :1               22:43   ?xdm?  21.03s  0.00s /bin/sh /usr/lib/gdm3/gdm-x-session

The JCPU value is the time used by all processes attached to the teletype (tty) terminal. It does not include past background jobs, but does include currently running background jobs.

The PCPU time is the time used by the current process named in the WHAT field.

last

The last command searches the /var/log/wtmp file and displays a list of all users logged in (and out) since /var/log/wtmp was created.

$ last
amnesia  :1           :1               Tue Aug  4 22:43   still logged in
reboot   system boot  5.7.0-1-amd64    Tue Aug  4 22:42   still running

wtmp begins Tue Aug  4 22:42:46 2020

One or more login names and/or ttys can be provided to last to only view entries for those login names.

Special Login Files

There are several special files that relate to user management:

/bin/false
If set as a user's login shell, they will not be able to log in.
${HOME}/.hushlogin
Changes the login process so that it does not perform a mail check, and does not display the last login information or the message of the day to the user.
/etc/issue
Contains the greeting that is output before a user is asked to log in.
/etc/login.defs
Defines the defaults for numerous commands (e.g., useradd, userdel, usermod, and groupadd). Includes entries for mail, password complexity and limitations, UID and GID minimum and maximum values, and whether the user's home directory is created by default.
/etc/motd
After a successful login, the contents of this file are displayed before the user's shell is executed. motd stands for Message of the Day.
/usr/sbin/nologin
If set as a user's login shell, this program displays a message that the account is unavailable and exits with a non-zero exit status. If the /etc/nologin file is present, no user can log into the system except for the root user and the content of the file (or /etc/nologin.txt) is displayed instead of a standard message.
/etc/securetty
Specifies from where the root user is allowed to log in from. If /etc/securetty does not exist, the root user can log in from anywhere.
/etc/usertty
Used to set the parameters for login locations, days, times, and systems that the user can connect from. Only used on systems that do not have pluggable authentication modules (PAM).

Documentation

You can learn more about the commands discussed in this post by referring to the Linux User's Manual, either at the command line, or online. Additional information on users, groups, and UIDs/GIDs can be found in the systemd documentation.

Enjoyed this post?

Subscribe to the feed for the latest updates.