Home Linux Admin Introduction Directory Tree Disks/File Systems Memory Mgmt Monitoring Startup/ShutDown Logging in/out User Accounts Backups Processes Cron Packages Books

User Accounts: Part 1


Contents



Introduction

How do we create new users in Linux ? Where are their passwords stored ? What are groups ? This chapter covers user management.

Etc files

There are 2 important files in thfe "/etc" folder that are relevant "passwd" and "group" .

1) passwd file
Every user in the system has an entry in this file .
The entry has the following format:

uname:password:uid:gid:gecos:home:shell

The "uname" refers to the user name.
The "password" is a legacy field. Passwords are not stored in this field
any more. Rather we are more likely to see a single letter "x" .
Passwords are kept in another file "/etc/shadow". If there is no letter "x" then
there might not be a password. If there is some other character than "x" then
the account is disabled.
The "uid" is a number denoting the user.
The "gid" is a number denoting the default group the user belongs to. However a user
can belong to multiple groups.
The "gecos" field contains information about the user such as full name.
The "home" field contains the home folder of the user who logs in.
The "shell" contains the shell that is started when the user logs in.
TODO
Login in to the hills server and try to find your username in the
passwd file. As an example:

[amittal@hills /]$ whoami
amittal
[amittal@hills /]$ cat /etc/passwd | grep "amittal"
amittal:x:2548:1258:Ajay MIttal:/users/amittal:/bin/bash
2) group file
Once a user is created a default group is assigned to the user. From above we can see that this is the 4th field in the "etc/group" file. A user can be part of additional groups. Every group has an entry in the "/etc/group" file. The entry in a group file has the following format:
gname:gpass:gid:members
The "gname" refers to the group name.
The "gpass" is generally not used is denoted by the letter "x". It can be
used to store encrypted password .
The "gid" is a number denoting the group id.
The "members" field is a comma seperated list of users that belong to this group.
If a member's default group is this group then the member is not listed. The below
commands show how we can find our entry for our group on the hills server.

[amittal@hills /]$ whoami
amittal
[amittal@hills /]$ cat /etc/passwd | grep "amittal"
amittal:x:2548:1258:Ajay MIttal:/users/amittal:/bin/bash
[amittal@hills /]$ cat /etc/group | grep "1258"
csdept:x:1258:

No members are listed for the "csdept" group and that means all the users
that belong to this group have their default group id as 1258.

We can also find out our default ( primary ) group
using the groups command.

[amittal@hills /]$ groups
csdept

TODO
Repeat the above commands for yourself on the hills server.

Passwords

We need to be familiar with couple of concepts before we study passwords. The concept of "hashing" refers to taking a text/string and computing a number A hash algorithm in cryptography works on a message ( message can be data of any length ) to produce a fixed size value. It is a one-way function and are the workhorses of encryption. They are used in anything involving digital signatures or certificates .

It should have the following properties.

1) If it runs on the same message again it should produce the same result.

2) It should not take a long time to run.

3) We should not be able to create a message given the hash ,

4) We should not be able to create 2 messages that produce the same hash.

5) A change to the message should produce a significant change in the hash.

Interesting thing about the hash function is that the algorithm will be
known to everyone and there is no key that is involved. Let us create
our own simple hashing algorithm .

If our message has characters then we use a variable storage where we
will add the ascii character value and then do a modulo 15 on it.

Example :   " C   A  T"

These translate to the following ascii numbers.

"67     65    84"

Initially "storage" has the value 0 .

storage = 0 + 67 modulus 15

            =  7

storage =  7 + 65 modulus 15 =

             =  72 modulus 15 =

             =   12

storage =   12 + 84  modulus 15

             =  96  modulus 15

             = 6

We know it satisfies
1). It will produce the same value of we run the hash algorithm
on the same message. But 4) is not true.

What happens if we increase one value then the modulus will carry
over and then decrease the next character and the end modulus will
decrease by 1 .

So instead of "C  A T"

we use "C B S"

storage = 0 + 67 modulus 15
           =  7
storage =  7 + 66 modulus 15
             =  73 modulus  15
            =   13
storage = 13 + 83 modulus 15
            =   96 modulus 15
            =   6

This hashing function is not going to cut it. One problem is that the hash is very small . It is less than 15 and only needs 4 bits. The other problem is the algorithm is too simple. We can easily guess how to break it.
MD4 was one of the early algorithms. It is deprecated and not secure but useful to study. It also provided the basis for other algorithms such as MD5, SHA-1 .
The hash is 128 bits. We start out with 4 integer variables initialized with specific values. The message is broken into 512 bits and operations are done with the 4 integer variables and these 512 bits. This block will change the value of the 4 integer variables. Then we fetch another block and this will change the values of the 4 integer variables also. We can use hash algorithm in passwords. Instead of storing passwords we instead store the hash of the password. When a user logs in we take the hash of the password and compare it to the stored hash. If they are equal then the password was entered correctly. This is more secure then storing the password directly. If the user forgets the password then we can reset the password. We can also add some random characers to the password and then do the hashing. This is called salting. It's possible that a person gains access to the hash and then uses a dictionary of commonly used passwords and their hashes. The user can then compare the hashes. However with salting the stored hash will be different. Of course we need to store the random characters also.
Passwords in Linux are stored in the file "/etc/shadow" file. We do not have permissions on the hills server to view this file so am using my standalone Linux machine.
root@ajkumar08-PC:/home/ajay# cat /etc/shadow | grep "ajay"
ajay:$y$j9T$3fl/BTt4A0rmwME0XjaTL0$XyhUm60nGpM4fxGhFYsuz14phptjL8/.nckUBx.45UB:
19401:0:99999:7:::

The first field ( as we can guess ) is the username.

Second field is $y$j9T$ ...
The "y" is the "yescript" algorithm and the "j9T" is the param and "3F..$" is the salt
and after the last "$" we have the hash.

The third field is the date of the last password change . A number of days since the epoch.
Jan 1, 1970 and this comes to February 13, 2023 for 19401.

The fourth field is the minimum number of days required between password changes. A 0
means there is no minimum.Password can be changed at any time.

The fifth field is the maximum number of days the password is valid and after that the
user is forced to change the password. For our case of "99999" that comes to 273 years.

The sixth field represents the number of days before the password expiration when a
warning is issued. In our case this is 7.

The seventh field is the number of days after expiration that the user is allowed
to login using their old password.
In our case this is empty and that means it is not enforced.

The eighth and last field is account expiration date. Account expiration means the
user cannot login after the expired date. Password expiration means user is not allowed
to login with the same password.
TO DO
Do a "man shadow" to see what each of the fields mean.
There is a utility called "chage" that we can use to update password information for a user. Unfortunately we cannot run this from the hills server.
root@ajkumar08-PC:/home/ajay# chage -E 2023-03-01  ajay
root@ajkumar08-PC:/home/ajay# cat /etc/shadow | grep "ajay"
ajay:$y$j9T$3fl/BTt4A0rmwME0XjaTL0$XyhUm60nGpM4fxGhFYsuz14phpt
jL8/.nckUBx.45UB:19401:0:99999:7::19417:
root@ajkumar08-PC:/home/ajay# chage -l ajay
Last password change                                    : Feb 13, 2023
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : Mar 01, 2023
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7
We changed the account expiration date with the "-E" option and shadow entry changed with the addition of 19417 in the 8th field. This is the number of days since 1/1/1970. We can check the date by using an online converter such as at:

Days since Epoch

Adding "19417" to 1/1/1970 produces the data 3/1/2023. We can also use the Linux command "date" to convert the no of days to the date.
By itself date will output the current date

ajay@ajkumar08-PC:~$ date
Sat 25 Feb 2023 08:51:38 AM PST

Shows the number of seconds elapsed since 1/1/1970
ajay@ajkumar08-PC:~$ date +%s
1677344063
ajay@ajkumar08-PC:~$

To convert the number of seconds to the date:

ajay@ajkumar08-PC:~$ date --date=@1677344063
Sat 25 Feb 2023 08:54:23 AM PST

To convert the number of days (19417) since Unix epoch we
convert the days to seconds and then use the above command.

ajay@ajkumar08-PC:~$ utime=$((19417*60*60*24))
ajay@ajkumar08-PC:~$ date --date=@$utime
Tue 28 Feb 2023 04:00:00 PM PST
Let's change the maximum number of days to 60.
root@ajkumar08-PC:/home/ajay# chage -M 60 ajay
root@ajkumar08-PC:/home/ajay# chage -l ajay
Last password change                                    : Feb 13, 2023
Password expires                                        : Apr 14, 2023
Password inactive                                       : never
Account expires                                         : Mar 01, 2023
Minimum number of days between password change          : 0
Maximum number of days between password change          : 60
Number of days of warning before password expires       : 7
The maximum number of days is 60. We add that to the date of the last password change to get "April 14th 2023". We can also get this date from the entry third field of 19401 and add 60 to it to get 19461. Converting this to a date gives us the same date of "April 14th 2023". Another utility is "passwd".
We are logged in as a normal user "ajay1"

$ passwd ajay1
Changing password for ajay1.
Current password:
New password:
Retype new password:
You must choose a longer password.
New password:
Retype new password:
passwd: password updated successfully
In it's simpleset form we can use it to change our passwords. We normally have to do this for new accounts as we login with an assigned password; the system will ask us to change our password. As we can see in the output above the system will not allow us to set a very simple password. However this restriction does not apply to an admin user.
An admin can set a simple password.

root@ajkumar08-PC:/home# passwd ajay1
New password:
Retype new password:
passwd: password updated successfully
root@ajkumar08-PC:/home#
We can use the "-d" option to delete the password for a user. This allows the user to login without a password.
The option is only available to admin user.

ajay@ajkumar08-PC:~$ passwd -d ajay1
passwd: Permission denied.
ajay@ajkumar08-PC:~$ su root
Password:
root@ajkumar08-PC:/home/ajay# passwd -d ajay1
passwd: password expiry information changed.
root@ajkumar08-PC:/home/ajay# exit
exit

To login to the user "ajay1" no password is required.
ajay@ajkumar08-PC:~$ su ajay1
$
$ exit
ajay@ajkumar08-PC:~$
We also have other options such as "-l" and "-u" . The "-l" will lock the password and the "-u" will unlock it. Locking the password means the user will not be able to login with the password till it is unlocked.
ajay@ajkumar08-PC:~$ su root
Password:

//Lock the password for ajay1
root@ajkumar08-PC:/home/ajay# passwd -l ajay1
passwd: password expiry information changed.
root@ajkumar08-PC:/home/ajay# exit
exit
ajay@ajkumar08-PC:~$ su ajay1
Password:
su: Authentication failure

//unable to login to ajay1 account

ajay@ajkumar08-PC:~$ su root
Password:

//unlock the password
root@ajkumar08-PC:/home/ajay# passwd -u ajay1
passwd: password expiry information changed.
root@ajkumar08-PC:/home/ajay# exit
exit
ajay@ajkumar08-PC:~$ su ajay1
Password:
$ exit
ajay@ajkumar08-PC:~$

Users

Linux is a multi-user system. That means we can have different user accounts and users can log in ("remotely") to the same system remotely. Some of the information that is relevant when creating a user is. Some of the steps involved are as follows:
1) Account is created. An entry is created in "/etc/passwd" file. Home
 directory is created.
2)The entry in "/etc/groups" updated if user is part of supplemental groups.
3) Startup files copied to the home directory.
4) The home directory's owner and group are set.
5) Password entry created in "/etc/shadow" file.
The useradd command has the following options.
These are the most important ones:

useradd [ -g group ] [ -G group,group,... ] [ -N ] [ -d home ] [ -s shell ]
[ -c gecos ] [ -m [ -k skeldir ] ] [ -M ] [ -r ] [ -p passwd ] username

-g group  use this as the default group

-G g,g,...  add the user to these secondary groups

-N  By default Linux creates a new group for each user. This option prevents
    that.

-d home  The path to the user's home directory

-s shell   The path to the program that will be run when
the user logs in.

-c gecos  The initial contents of the GECOS field. Normally,
the user's real name is used here.

-m  create the user's home directory. If -m is used, -k skeldir
can be used to specify the directories to copy the user startup files from.

-M do not create the user's home directory

-r create a system account rather than a user account.
(This determines the range that the account's uid will be in.)

-p password  Here, password is the encrypted password.
Usually, the passwd program is run after the account is
created to assign the password.
username is the user's name (the login name).
It must be unique.
We only need to give the username as the argument. The default values are obtained from "/etc/login.defs" and "/etc/default/useradd" .
Let's look at some of the
values in these 2 files.
"/etc/default/useradd"
# GROUP=100

If a value is not specified then a default group with the same name as the user is
created and the user assigned to this group. Example for user: "ajay" on my personal
Linux system.

ajay@ajkumar08-PC:~$ cat /etc/passwd | grep "ajay"
ajay:x:1000:1000:ajay,,,:/home/ajay:/bin/bash
ajay1:x:1001:1001::/home/ajay1:/bin/sh
ajay@ajkumar08-PC:~$ cat /etc/group | grep "1000"
ajay:x:1000:
ajay@ajkumar08-PC:~$

If we do have a value for "GROUP" in the "useradd" file then we need to specify the
"-N" option in useradd to tell it not to create the group with the same name as user.

#
# The SKEL variable specifies the directory containing "skeletal" user
# files; in other words, files such as a sample .profile that will be
# copied to the new user's home directory when it is created.
# SKEL=/etc/skel

This folder will have the default initialization files. These are hidden files.
On the hills server we have the following files for my account.

[amittal@hills ~]$ ls -a | grep "^\."
.
..
.bash_history
.bash_logout
.bash_profile
.bashrc
.cache
.config
.emacs
.emacs.d
.history
.kshrc
.oracle_jre_usage
.pki
.python_history
.sh_history
.ssh
.viminfo
[amittal@hills ~]$





"/etc/login.defs"

[amittal@hills ~]$ cat /etc/login.defs | grep "HOME"
CREATE_HOME     yes

This variable indicates whether creating the home directory is the default.
Recall that this is the same as "-m" from the command "useradd" .