Setting Up User Accounts

This chapter covers the following topics:

Starting a user session

Access to all QNX resources and system functions is controlled when a user attempts to login to the system. A user sitting at a terminal /dev/ser1 can gain access to the system by entering correct responses to the following command:

on -t /dev/ser1 /bin/login

When invoked without options, the login utility prompts the user for a username and password. You can automate the login process through the tinit utility. To have tinit start the login process automatically at system startup, you would add the following entry to the node's sysinit.node file:

tinit -t /dev/ser1 &

Setting environment variables

When a user starts a session, the login Shell program is started. See the login man page in Utilities Reference for information about how the Shell variables and defaults are established.

Additional settings are retrieved from the user's /home/userID/.profile file (~/.profile) if it exists. The Shell may add some of the values it requires to the user's .profile file automatically. For example, a user's .profile file may include settings for the following environment variables:

TERM= defines the user's terminal type (e.g. qnx or qansi — for a list of the possible values, see the Setting Up Terminals chapter)
TMPDIR=gives the location of temporary work space that utilities and programs may use (e.g. /tmp)
TZ=sets the time zone (e.g. TZ=EST5EDT4)

The set command can set (+) or unset (-) these shell options. To display a list of the variables that have been defined for your shell, you'd type set at the Shell prompt. To see the value of one variable, you'd type echo $variable_name at the Shell prompt (e.g. echo $WORKDIR). For more information about these Shell commands, see the sh utility in the Utilities Reference.

Shell initialization

The /etc/profile file is the first file executed by the login Shell. Local conventions can be established through this file.

The user-specific startup profile file, typically $HOME/.profile, is executed next. You can add any exported environment variables you require to this file. For example, if you'd like to preserve your login Shell settings whenever a process starts a new shell on your behalf, be sure to define and export the ENV environment variable in your .profile file. For example:

export ENV=$HOME/.kshrc

This entry ensures that every time a new shell starts, the /home/.kshrc file will be executed. To display the values of all exported variables, type export -p.

Shell scripts

You can write shell scripts that contain Shell commands and options. A Shell script can be executed as a command or in batch mode as a command-line argument to the Shell. For more information about shell scripts, see the sh utility in the Utilities Reference.

Security

QNX provides mechanisms to control access to resources and critical system functions. These mechanisms are based on the ability of the system to identify a particular user.

When the system boots for the first time (right after the initial installation), you're automatically logged in as the superuser (root). This username allows access to every part of the system and doesn't require a password.

To prevent unauthorized users from accessing the system, you should give root a password. You can create a new user account for yourself that you can use afterwards for your daily work. The passwd utility allows a login password to be changed; you can use the utility to create new usernames for yourself and others.

Access control utilities

The QNX access control utilities are:

  • login — sign on to the system
  • su — temporarily become another user
  • passwd — create and maintain user accounts/change passwords

The login utility

The login utility should be started by tinit on all tty devices. The utility demands a username and password, and verifies them against the user database /etc/passwd before granting access to the system. If the username/password combination is incorrect, login displays a message to that effect and terminates. If the user enters the correct combination, login starts the login Shell and loads that user's environment.

The su utility

The su utility lets you temporarily have the privileges of another user. If a user ID isn't entered on the command line when you start su, the utility prompts for a password that must match the superuser's password. Entering a valid access combination causes su to access the user database /etc/passwd and create a shell that has all the rights and privileges of the assumed user ID. Exiting from the shell returns you to your regular user ID.

The passwd utility

The passwd utility can be used to change passwords or to add a new user account to the system. Anyone can change their own password, but the superuser (root) is the only user who has the right to create new user accounts. In both cases, the passwd utility locks access to the user password file /etc/passwd to prevent any other attempts to access the file while it's being modified.

Before you start creating user IDs, you might want to modify passwd's behavior. The settings in the file /etc/default/passwd determine which local policies will be enforced by passwd, such as the stringency of passwords, user ID ranges, and so on. For more information about the options you can set, see the passwd utility in the Utilities Reference.

A user invokes passwd with his or her own user ID to change the corresponding password. The passwd utility will prompt the user for the required information. When the user is the superuser, the old password isn't requested.

The superuser can add a new account by invoking passwd with a unique user ID. The utility prompts for information that will control the new user's environment, including access privileges. The account permissions to include comprise the user's group ID assignment and file permissions.

For example, to create a new account with the username carol, the superuser would enter:

passwd carol

By default, passwd will then prompt for the following information:

  • user ID number
  • group ID assignment
  • user's real name
  • user's home directory
  • initial command
  • initial password

User ID number

By convention, user accounts have a user ID >= 100. User IDs below 100 are often used by system processes. User ID ranges are set in the /etc/default/passwd file.

Group ID assignment

If the group ID doesn't exist, a reminder to update the group file /etc/group will be displayed.

The /etc/group file grants privileges to all users who are members of a defined group. For example, the “Finance” department would be allowed access to the company's financial records, but the “Customer Support” group would not. You can set up a group ID for “Finance” with the required access permissions and assign users to that group according to the privileges they require.

The /etc/group file contains a list of users by group. Each line has the following general syntax:

groupname::group_ID:user1, user2, user3, ..., userN

For example, the following entry defines the group “docs” with group ID “124”, and members “johno”, “chrish”, “eric”, “stever”, and “rachel.”

docs::124:johno, chrish, eric, stever, rachel

Initially you'd add groups that have no users, as in the following example:

docs::0:
techies::1:
support::2:
marketing::3:
finance::4:

When a user logs in, the value in the password database /etc/passwd will specify the default group ID a user has been assigned to (if any). Users who belong to a group are allowed to switch to the privileges of that group any time using the newgrp command.

Home directory, initial command, and initial password

The home directory, initial command, and initial password items are optional. If you don't specify a value, the following defaults are used:

home directory/home/username is used (it's created if it doesn't exist)
initial commandthe default Shell startup command (/bin/sh) is executed immediately after the user logs in
passwordthe user account is created without a password

Deleting a user account

QNX doesn't provide a direct mechanism for deleting accounts. To delete an account, you must remove the user database entry from the /etc/passwd file, the username from the corresponding group ID assignment entry in the /etc/group file, and the corresponding encoded login password entry from /etc/shadow file.

More about user and group IDs

Upon logging in, a user is assigned two pieces of information:

  • a user ID
  • a group ID

These are known as the user's real user ID and real group ID.

The user ID should be unique — no two users should share the same user ID. This rule can be enforced by the passwd utility, but the superuser can override the rule by editing the password file directly.

The group ID allows several users to be associated with a group. This group mechanism lets a team of users share resources without making those resources available to the rest of the world. For more information about the /etc/group file and its contents, see the newgrp utility in the Utilities Reference.

Effective user and group IDs

Processes have two classes of user and group IDs: real and effective. When a process is created, it automatically inherits these four IDs from its parent (which is typically the login Shell):

  • real user ID
  • real group ID
  • effective user ID
  • effective group ID

The effective user and group IDs are used for permission checking. A process can change its effective user or group ID, or both, so that they differ from their real counterparts. Typically, this is done to gain access to resources that aren't available to the real user and group IDs.

To modify effective
group and user IDs:
You use the:
from within C programsseteuid() and setegid() functions
from within the Shellsu and newgrp utilities to set the setuid and setgid file permission bits
while running a Shell programsu command to change to root (provided you know the superuser's password), then edit the /etc/passwd file

For more information on setuid and setgid, see the “File permissions” section.

The newgrp utility

The newgrp utility starts a new Shell with different real and effective group IDs. When invoked without arguments, newgrp switches the group ID to the one identified in the password database for the current user. The password database controls the groups that a particular user may switch to.

File permissions

In QNX, each file has an associated set of permissions called mode bits. These mode bits, in conjunction with the file's owner and group, control access to the file.

When a process creates a file, the process's effective user ID and effective group ID become the file's owner and group. A set of mode bits is also assigned to the file (this is described in the “How mode bits are assigned” section).

There are three classes of mode bits:

  • owner
  • group
  • other

When a process attempts to access the file, the Filesystem Manager honors the appropriate class of mode bits. The Filesystem Manager determines which mode bits to honor by performing a few comparisons in a specific order:

  1. The effective user ID of the requesting process is compared to the owner of the file. If they match, the owner mode bits are honored.
  2. If the owner comparison fails, the requesting process's effective group ID is compared to the file's group ID. If these group IDs match, the group mode bits are honored.
  3. If both the owner and group comparisons fail, the other mode bits are honored.
As root (uid 0), you can access any file for read/write regardless of the permissions, and you can execute any file that has at least one mode bit permitting execute access.

The file mode bits are stored in the 16-bit st_mode field of the directory entry for the file; access is granted if a mode bit is set.

Opening screen

As the following table shows, permissions affect regular files and directories differently:

This bit:Affects:Affects directories by:
rReading the fileExamining the names of files in the directory (e.g. via ls)
wWriting to the fileCreating, removing, and renaming files within the directory, including subdirectories
xExecuting the fileSearching the directory. This means you can change your current working directory to this directory. Also, you may include this directory within pathnames (e.g. in open(), stat(), etc.)
Execute permission has meaning only for directories and regular files; it doesn't apply to other file types.

Viewing permissions

You can use the ls -l (“el”) command to see a file's permissions, owner, and group. The following ls -l output for the file alpha.c shows that the owner and anyone in the techies group may read and write to the file, while other users may only read it:

-rw-rw-r--  1 rachel   techies   8475 Apr 8  1996 alpha.c

In the following example, the ls -ld output for the directory /bin shows that the owner and group members may read, write, and search the directory, while other users don't have write permissions and therefore can't add any new files to the directory:

drwxrwxr-x  2 root     techies   2048 Sep 19  1990 bin

But note that other users may still list or execute files in /bin.

It's possible — though unusual — to have read permission on a directory but not search permission. For example, ls could work (depending on the options you give it), but you wouldn't be able to access any file in the directory or do a cd to the directory.

How mode bits are assigned

The permissions on a file are derived by combining the current umask of the creating process with that process's requested open()/creat() mode.

The umask is a permission bit mask that indicates which permission bits are to be turned off if a process specifies default permission when a file, directory, or FIFO is created (see umask in the Utilities Reference).

The mask is the logical AND of the mode and the complement of the umask. For example, if the mode requests read-write permission for everyone as follows:

BinaryOctalSymbolic
110 110 110 0666rw- rw- rw-

and the umask indicates write permission for group and other:

BinaryOctalSymbolic
000 010 0100022--- -w- -w-

then the result is read-write permission for the owner, and read permission for everyone else:

BinaryOctalSymbolic
110 100 1000644rw- r-- r--

Changing permissions

You can change the permissions of a file with the following commands:

To:Use:
change owner and groupchown and chgrp utilities, or chown() function (C programs)
change access permissions, and setuid and setgid mode bitschmod utility or chmod() function (C programs)
set the file mode creation maskumask utility

To modify the owner or access permissions of a file, your effective user ID must match that of the file's owner. If you change the owner of the file to be other than yourself, you'll no longer be able to change the permissions and ownership of the file. The superuser can modify the mode bits of any file, regardless of who owns the file.

setuid and setgid

To perform certain functions, a user must sometimes run a command at a privilege level higher than their own. For example, a user may need to run the passwd utility to modify their own entry in the password database, even though they would normally be denied write access to that database.

Two file mode bits allow a user to run a command at a higher privilege level:

  • setuid (set-user-ID)
  • setgid (set-group-ID)

With these bits set, an executable file will run with the privileges of its owner and group rather than with the privileges of the process that invokes the file. These mode bits apply only to executable regular files.

When a file is loaded for execution and the setuid mode bit is set, the effective user ID of the new process becomes that of the file's owner. Similarly, if the setgid mode bit is set, the effective group ID becomes that of the file's group.

To close a potential security hole, the setuid and setgid bits are cleared any time the file ownership (owner or group) is changed. This prevents users from writing an executable file to disk, setting the setuid bit, and then changing the ownership of the file to root, thereby gaining unlimited system access.

The passwd, login, su, and newgrp utilities are all setuid to root; these programs therefore run with the permissions of the superuser.

By convention, root is the only user with user ID zero, which yields superuser status. With respect to access control, you must ensure that only programs that can be trusted — and absolutely need to be trusted — are setuid to root. No special privileges are bestowed on a program when it's setgid to root.

Since all programs setuid to root inherit superuser capabilities, you should make sure they do not have general write permissions so that only the superuser will be able to modify the programs.

The password database

Three files collectively form the password database:

  • /etc/passwd
  • /etc/shadow
  • /etc/group

The access permissions to these files should be set as follows:

File:Owner:Group:Permissions:
/etc/passwdrootrootrw- r-- r--
/etc/grouprootrootrw- r-- r--
/etc/shadowrootrootrw- --- ---

/etc/passwd

The /etc/passwd file contains a set of lines in the following format:

username:haspw:userid:group:comment:homedir:shell

where:

usernamelogin name of user
haspwif empty, user has no password; if x, user's password is in the /etc/shadow file. An empty value or a value of x are the only permitted values.
useridnumeric user ID
groupnumeric group ID
commenta free-form comment field; must not contain “:
homedirhome directory of this user (default is /)
shellinitial command (and arguments) to start after login (default is /bin/sh)

/etc/group

The /etc/group file contains lines in the following format:

groupname::group_ID:user_ID[,user_ID]*

where:

groupnamename of the group
group_IDnumeric ID of the group
user_IDone or more user IDs belonging to this group

/etc/shadow

The /etc/shadow file contains lines in the following format:

user_ID:password:0:0:0

where:

user_IDname of this user
passwordencrypted password of this user

You may notice from the above permission list that /etc/passwd is readable by anyone. This is to provide standard utilities with a simple mechanism to find information about users. Since this file is readable, the encrypted password isn't stored in it.

The encrypted password is stored in the /etc/shadow file, which is readable only by the superuser. This is to inhibit unauthorized attempts to decrypt the passwords. To protect the security of your user community, you should ensure that these permissions are maintained.

QNX is shipped with a default password database that includes /etc/passwd and /etc/group. The /etc/shadow file isn't shipped, because the accounts initially don't have passwords associated with them.

Default password files

The default /etc/passwd file that was shipped with your QNX system contains the following:

root::0:0::/:/bin/sh

The default /etc/group file contains the following:

root::0:root

Accounting file

The login utility updates system accounting information, which is logged to the /etc/acclog file. If this file doesn't exist, all accounting information will be discarded. This is the normal mode of operation after QNX has been installed.

For most realtime systems, this default of discarding accounting information is recommended. If you have a dial-up line to a computer or if you run QNX on a network of many users, you may wish to change this default by creating an empty /etc/acclog file.

Enabling accounting

To enable accounting, you create an empty /etc/acclog file. You can do this using the touch utility:

touch /etc/acclog
chmod g=,o= /etc/acclog

Once this file is created, accounting information will be logged here.

Note that only the superuser (user ID root) may create and modify this file.

Record format

Each record in the /etc/acclog file is of the form:

tttttttttt cc data...

where tttttttttt is the time in seconds since 1970 (in decimal). This is always followed by a single space. The time is followed by a two-character code cc. This code is then followed by a space and data specific to each code. Each line is terminated by a Newline character. The following utilities write to the /etc/acclog file:

Utility:Purpose:Record:
loginuser logged intttttttttt LO device uid gid uname
loginlogin failedtttttttttt LF device uname
modemmodem connecttttttttttt MO device baud
suswitch usertttttttttt SU device uid gid uname
tinitstart a commandtttttttttt TS device command
tinitarm a devicetttttttttt TA device

A typical accounting file might look like this:

670464500 TS //1/dev/ser1 modem -b 19200 -L
670464545 MO //1/dev/ser1 2400
670464550 LO //1/dev/ser1 100 101 steve
670465824 TS //1/dev/ser1 modem -b 19200 -L

This record shows that tinit started a modem program to wait for calls. A call was received and answered at 2400 baud, and user ID steve logged in. Note that the log doesn't show a logout. The logout is inferred, because in the final entry tinit starts another modem program.

The total connect time for the user (from successful login) can be calculated thus:

670465824 - 670464550 = 1274 seconds

On a busy system, records from many devices will be interspersed throughout the accounting file. In order to match events keyed to each device, you'll find an associated node number that lets you track accounting records for all devices throughout a network in a single logfile.

Here are several common event sequences:

Event sequence:Meaning:
TS --> LO --> TSA login and logout on a dedicated line.
TS --> MO --> LO --> TSA login and logout on a dial-up line.
TA --> TS --> LO --> TA A login and logout on a dedicated line armed by a keystroke.
TS --> TSAn unsuccessful login on a dedicated line.
TS --> MO --> TSAn unsuccessful login on a dial-up line.

Clearing the logfile

Once you create /etc/acclog, it will start to grow as records are appended to it. If left unmanaged, this file may grow to consume considerable disk space, so you should print or archive the information in this file on a regular basis. You may even want to automate this housekeeping job using the cron utility (see the Utilities Reference).

The following commands move the accounting file to a file named by year and month and create a new empty log:

mv /etc/acclog /etc/acclogs/9607
touch /etc/acclog
chmod g=,o= /etc/acclog

Compressing the log file

Since the data in this file is very regular, you may use the freeze compression utility, which will achieve very high rates of compression on the file. This can significantly reduce disk space requirements if you keep the saved logs online or save them to a floppy.

Remember to move the file before compressing it. Never compress /etc/acclog directly.

Here's an example of the recommended compression procedure:

mv /etc/acclog /etc/logs/9607
touch /etc/acclog
chmod g=,o= /etc/acclog
freeze /etc/logs/9607

Note also that other utilities (possibly third-party) may add their own accounting records to the /etc/acclog file.

Other log files

To have QNX start recording events in a log file, simply create an empty log file in the appropriate directory. You must use the filenames given below. QNX will start logging system events as soon as the associated log file exists.

/etc/syslog

QNX utilities log problems or unexpected events to the /etc/syslog text file.

/usr/adm/syslog

The logger utility appends lines to the /usr/adm/syslog file. As long as a program has write access to this file, it can run logger as a setuid process owned by adm:adm.

/usr/adm/lastlog

The login utility writes information to the /usr/adm/lastlog file (provided it exists). It can be used to track where and when a user last logged in. The finger utility can display information from the lastlog file by user.

$HOME/.lastlogin

The file $HOME/.lastlogin is created by login. It keeps track of the last time the user logged in, and from which device. The contents of this file are displayed when a user logs in. If a user hasn't logged in since the message of the day (motd) was last updated, the contents of the file /etc/motd (provided it exists) are printed to the user's terminal instead.

/etc/nologin

The presence of an /etc/nologin file prevents anyone from logging in.

/etc/wtmp

The /etc/wtmp file maintains a list of who is currently on the system and how these users are logged in. TCP/IP for QNX uses this information.

/etc/utmp

The /etc/utmp file is updated by login. It contains login information in binary format and maintains a history of all changes to /etc/wtmp.