LDP/LDP/guide/docbook/Pocket-Linux-Guide/phase6.xml

506 lines
19 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter id="phase6">
<title>Enabling Multiple Users</title>
<sect1>
<title>Analysis</title>
<para>Up to now the system has been operating in single-user mode. There
is no login process and anyone who boots the system goes straight into a
shell with root privileges. Obviously, this is not the normal operating
mode for most GNU/Linux distributions. Most systems feature multi-user
capability where many users can access the system simultaneously with
different privilege levels. These multi-user systems also support virtual
consoles so that the keyboard and video display can be multiplexed between
several terminal sessions. So in this phase we would like to add the
following enhancements to the system:</para>
<itemizedlist>
<listitem>
<para>Enable multi-user capability.</para>
</listitem>
<listitem>
<para>Create multiple, virtual consoles.</para>
</listitem>
</itemizedlist>
</sect1>
<sect1>
<title>Design</title>
<sect2>
<title>The login process</title>
<para>The From-Powerup-To-BASH-Prompt-HOWTO does a good job of outlining
the steps in the login process. Basically it works like this.</para>
<orderedlist>
<listitem>
<para>The <command>init</command> daemon starts a
<command>getty</command> process on the terminal.</para>
</listitem>
<listitem>
<para>The <command>getty</command> program displays the contents of
<filename>/etc/issue</filename> and prompts for a user name.</para>
</listitem>
<listitem>
<para>When the user name is entered, control is handed off to the
<command>login</command> program.</para>
</listitem>
<listitem>
<para>The <command>login</command> program asks for a password and
verifies the credentials using <filename>/etc/passwd</filename>,
<filename>/etc/group</filename> and possibly
<filename>/etc/shadow</filename>.</para>
</listitem>
<listitem>
<para>If everything is okay the user's shell is started.</para>
</listitem>
</orderedlist>
</sect2>
<sect2>
<title>Obtaining source code</title>
<para>The <command>getty</command> and <command>login</command> programs
were already installed as part of the util-linux package so there is no
need to download any new source code.</para>
</sect2>
<sect2>
<title>Creating support files</title>
<sect3>
<title>Device nodes</title>
<para>Details about virtual console device files can be found in the
Linux kernel source code file called <filename>devices.txt</filename>
in the <filename>Documentation</filename> directory. We will need to
create <filename>tty1</filename> through <filename>tty6</filename> for
each of the virtual consoles as well as <filename>tty0</filename> and
<filename>tty</filename> to represent the current virtual
console.</para>
</sect3>
<sect3>
<title>/etc/issue</title>
<para>The <filename>/etc/issue</filename> file is pretty easy to
construct. It can contain any text we want displayed on the screen
prior to the login prompt. It could be something friendly like
"Welcome to Pocket Linux", something menacing like "Authorized users
only!" or something informational like "Connected to tty1 at 9600bps".
The agetty(8) manpage explains how to display information like tty
line and baud rate using escape codes.</para>
</sect3>
<sect3>
<title>/etc/passwd</title>
<para>The format of <filename>/etc/passwd</filename> can be obtained
by reading the passwd(5) manpage. We can easily create a user account
by adding a line like "root::0:0:superuser:/root:/bin/sh" to the
file.</para>
<para>Maintaining passwords will be somewhat challenging because of
the system being loaded into ramdisk. Any changes to
<filename>/etc/passwd</filename> will be lost when the system is
shutdown. So to make things easy, we will create all users with null
passwords.</para>
</sect3>
<sect3>
<title>/etc/group</title>
<para>The structure of <filename>/etc/group</filename> is available
from the group(5) manpage. A line of "root::0:root" would define a
group called "root" with no password, a group id of zero and the user
root assigned to it as the only member.</para>
</sect3>
<sect3>
<title>Conventions</title>
<para>User and group names and id's are generally not chosen at
random. Most Linux systems have very similar looking
<filename>/etc/passwd</filename> and <filename>/etc/group</filename>
files. Definitions for commonly used user id and group id assignments
may be found in one of several places:</para>
<itemizedlist>
<listitem>
<para>The <filename>/etc/passwd</filename> and
<filename>/etc/group</filename> files on any popular GNU/Linux
distribution.</para>
</listitem>
<listitem>
<para>The Debian Policy Manual -- available online at <ulink
url="http://www.debian.org/doc/debian-policy">http://www.debian.org/doc/debian-policy</ulink>.</para>
</listitem>
<listitem>
<para>The Linux Standard Base specification -- downloadable in
many formats from <ulink
url="http://www.linuxbase.org/spec/index.shtml">http://www.linuxbase.org/spec/index.shtml</ulink>.</para>
</listitem>
<listitem>
<para>Essential System Administration, 3rd Edition by Aeleen
Frisch -- available at libraries, bookstores or directly from
O'Reilly Publishing at <ulink
url="http://www.oreilly.com/">http://www.oreilly.com/</ulink>.</para>
</listitem>
</itemizedlist>
</sect3>
</sect2>
<sect2>
<title>Dependencies</title>
<para>Running <command>ldd</command> on the <filename>login</filename>
program from util-linux will reveal that it is linked to the libraries
<filename>libcrypt.so.1</filename>, <filename>libc.so.6</filename> and
<filename>ld-linux.so.2</filename>. In addition to these libraries there
is another, unseen dependency on <filename>libnss_files.so.2</filename>
and the configuration file
<filename>/etc/nsswitch.conf</filename>.</para>
<para>The name service switch library
<filename>libnss_files.so.2</filename> and
<filename>nsswitch.conf</filename> are required for
<filename>libc.so.6</filename>, and consequently the
<filename>login</filename> program, to access the
<filename>/etc/passwd</filename> file. Without libnss and its
configuration file, all logins will mysteriously fail. More information
about glibc's use of the name service switch libraries can be found at
<ulink
url="http://www.gnu.org/software/libc/manual/html_node/Name-Service-Switch.html">http://www.gnu.org/software/libc/manual/html_node/Name-Service-Switch.html</ulink>.</para>
</sect2>
<sect2>
<title>Assigning ownership and permissions</title>
<para>Previously, with the single user system, there was no need to
worry about permissions when installing directories, files and device
nodes. The shell was effectively operating as root, so everything was
accessible. Things become more complex with the addition of multiple
user capability. Now we need to make sure that every user has access to
what they need and at the same time gets blocked from what they do not
need.</para>
<para>A good guideline for assigning ownership and permissions would be
to give the minimum level of access required. Take the
<filename>/bin</filename> directory as an example. The Filesystem
Hierarchy (FHS) document says, "<filename>/bin</filename> contains
commands that may be used by both the system administrator and by
users". From that statement we can infer that <filename>/bin</filename>
should have read and execute permission for everyone. On the other hand,
the <filename>/boot</filename> directory contains files for the boot
loader. Chances are good that regular users will not need to access
anything in the <filename>/boot</filename> directory. So the minimum
level of access would be read permission for the root user and other
administrators who are members of the root group. Normal users would
have no permissions assigned on the <filename>/boot</filename>
directory.</para>
<para>Most of the time we can assign similar permissions to all the
commands in a directory, but there are some programs that prove to be
exceptions to the rule. The <command>su</command> command is a good
example. Other commands in the /bin directory have a minimum requirement
of read and execute, but the <command>su</command> command needs to be
setuid root in order to run correctly. Since it is a setuid binary, it
might not be a good idea to allow just anyone to run it. Ownership of
0:0 (root user, root group) and permissions of rwsr-x--- (octal 4750)
would be a good fit for <command>su</command>.</para>
<para>The same logic can be applied to other directories and files in
the root filesystem using the following steps:</para>
<orderedlist>
<listitem>
<para>Assign ownership to the root user and root group.</para>
</listitem>
<listitem>
<para>Set the most restrictive permissions possible.</para>
</listitem>
<listitem>
<para>Adjust ownership and permissions on an "as needed"
basis.</para>
</listitem>
</orderedlist>
</sect2>
</sect1>
<sect1>
<title>Construction</title>
<sect2>
<title>Verify presence of getty and login</title>
<para><programlisting><prompt>bash#</prompt> ls ~/staging/sbin/getty
<prompt>bash#</prompt> ls ~/staging/bin/login</programlisting></para>
</sect2>
<sect2>
<title>Modify inittab for multi-user mode</title>
<para>Modify <filename>~/staging/etc/inittab</filename> by changing the
default runlevel and adding <command>getty</command> entries as shown
below.</para>
<para><programlisting># /etc/inittab - init daemon configuration file
#
# Default runlevel
id:2:initdefault:
#
# System initialization
si:S:sysinit:/etc/init.d/rc S
#
# Runlevel scripts
r0:0:wait:/etc/init.d/rc 0
r1:1:respawn:/bin/sh
r2:2:wait:/etc/init.d/rc 2
r3:3:wait:/etc/init.d/rc 3
r4:4:wait:/etc/init.d/rc 4
r5:5:wait:/etc/init.d/rc 5
r6:6:wait:/etc/init.d/rc 6
#
# Spawn virtual terminals
1:235:respawn:/sbin/getty 38400 tty1 linux
2:235:respawn:/sbin/getty 38400 tty2 linux
3:235:respawn:/sbin/getty 38400 tty3 linux
4:235:respawn:/sbin/getty 38400 tty4 linux
5:235:respawn:/sbin/getty 38400 tty5 linux
6:2345:respawn:/sbin/getty 38400 tty6 linux
#
# end of /etc/inittab</programlisting></para>
</sect2>
<sect2>
<title>Create tty devices</title>
<para><programlisting><prompt>bash#</prompt> cd ~/staging/dev
<prompt>bash#</prompt> mknod ~/staging/dev/tty0 c 4 0
<prompt>bash#</prompt> mknod ~/staging/dev/tty1 c 4 1
<prompt>bash#</prompt> mknod ~/staging/dev/tty2 c 4 2
<prompt>bash#</prompt> mknod ~/staging/dev/tty3 c 4 3
<prompt>bash#</prompt> mknod ~/staging/dev/tty4 c 4 4
<prompt>bash#</prompt> mknod ~/staging/dev/tty5 c 4 5
<prompt>bash#</prompt> mknod ~/staging/dev/tty6 c 4 6
<prompt>bash#</prompt> mknod ~/staging/dev/tty c 5 0</programlisting></para>
</sect2>
<sect2>
<title>Create support files in /etc</title>
<sect3>
<title>/etc/issue</title>
<para>Create the file <filename>~/staging/etc/issue</filename> using
the example below or design a customized message.</para>
<para><programlisting>Connected to \l at \b bps.</programlisting></para>
<para>Be sure that "\l" is a lowercase letter L and not the number
one.</para>
</sect3>
<sect3>
<title>/etc/passwd</title>
<para>Use a text editor to create a minimal passwd file conforming to
the Linux Standards Base (LSB) document. Save the file as
<filename>~/staging/etc/passwd</filename></para>
<para><programlisting>root::0:0:Super User:/root:/bin/sh
bin:x:1:1:Legacy UID:/bin:/bin/false
daemon:x:2:2:Legacy UID:/sbin:/bin/false</programlisting></para>
</sect3>
<sect3>
<title>/etc/group</title>
<para>Use a text editor to create an LSB conforming group file and
save it as <filename>~/staging/etc/group</filename></para>
<para><programlisting>root::0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon</programlisting></para>
</sect3>
<sect3>
<title>/etc/nsswitch.conf</title>
<para>Create the following file and save it as
<filename>~/staging/etc/nsswitch.conf</filename></para>
<para><programlisting>passwd: files
group: files</programlisting></para>
</sect3>
</sect2>
<sect2>
<title>Copy required libraries</title>
<para><programlisting><prompt>bash#</prompt> cp /lib/libnss_files.so.2 ~/staging/lib
bash# strip --strip-unneeded ~/staging/lib/*</programlisting></para>
</sect2>
<sect2>
<title>Set directory and file permissions</title>
<para>Set minimal privileges on all files and directories under
<filename>~/staging</filename>. Everything is owned by the root user and
the root group. Permissions are read-write for the owner and read-only
for the group. Exceptions to the blanket permissions are handled case by
case.</para>
<para><programlisting><prompt>bash#</prompt> cd ~/staging
<prompt>bash#</prompt> chown -R 0:0 ~/staging/*
<prompt>bash#</prompt> chmod -R 640 ~/staging/*</programlisting></para>
<para>Set execute permission on all directories. (Note the capital
"X")</para>
<para><programlisting><prompt>bash#</prompt> chmod -R +X ~/staging/*</programlisting></para>
<para>Files in <filename>/bin</filename> are read and execute for all,
but <filename>su</filename> is an exception.</para>
<para><programlisting><prompt>bash#</prompt> chmod 755 ~/staging/bin/*
<prompt>bash#</prompt> chmod 4750 ~/staging/bin/su</programlisting></para>
<para>Files in <filename>/dev</filename> have various permissions. Disk
devices should be accessible to administrators only. Other files like
<filename>/dev/null</filename> should have full privileges granted to
everyone.</para>
<para><programlisting><prompt>bash#</prompt> chmod 660 ~/staging/dev/fd0 dev/ram0
<prompt>bash#</prompt> chmod 666 ~/staging/dev/null
<prompt>bash#</prompt> chmod 622 ~/staging/dev/console
<prompt>bash#</prompt> chmod 600 ~/staging/dev/initctl
<prompt>bash#</prompt> chmod 622 ~/staging/dev/tty
<prompt>bash#</prompt> chmod 622 ~/staging/dev/tty?</programlisting></para>
<para>The <filename>passwd</filename> and <filename>group</filename>
files must be world readable.</para>
<para><programlisting><prompt>bash#</prompt> chmod 644 ~/staging/etc/passwd
<prompt>bash#</prompt> chmod 644 ~/staging/etc/group</programlisting></para>
<para>The scripts in <filename>/etc/init.d</filename> are read and
execute for administrators.</para>
<para><programlisting><prompt>bash#</prompt> chmod 750 ~/staging/etc/init.d/*</programlisting></para>
<para>Libraries need read and execute permissions for everyone.</para>
<para><programlisting><prompt>bash#</prompt> chmod 755 ~/staging/lib/*</programlisting></para>
<para>Only root should have access to the <filename>/root</filename>
directory.</para>
<para><programlisting><prompt>bash#</prompt> chmod 700 ~/staging/root</programlisting></para>
<para>Make files in <filename>/sbin</filename> read and execute for
administrators.</para>
<para><programlisting><prompt>bash#</prompt> chmod 750 ~/staging/sbin/*</programlisting></para>
<para>Temp should be read-write for all with the sticky bit set.</para>
<para><programlisting><prompt>bash#</prompt> chmod 1777 ~/staging/tmp</programlisting></para>
</sect2>
<sect2>
<title>Create the root disk image</title>
<para><programlisting><prompt>bash#</prompt> cd /
<prompt>bash#</prompt> dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
<prompt>bash#</prompt> mke2fs -m0 /dev/ram7 4096
<prompt>bash#</prompt> mount /dev/ram7 /mnt
<prompt>bash#</prompt> cp -dpR ~/staging/* /mnt
<prompt>bash#</prompt> umount /dev/ram7
<prompt>bash#</prompt> dd if=/dev/ram7 of=~/phase6-image bs=1k count=4096
<prompt>bash#</prompt> gzip -9 ~/phase6-image</programlisting></para>
</sect2>
<sect2>
<title>Copy the image to diskette</title>
<para>Insert the diskette labeled "root disk" into drive fd0.</para>
<para><programlisting><prompt>bash#</prompt> dd if=~/phase6-image.gz of=/dev/fd0 bs=1k</programlisting></para>
</sect2>
</sect1>
<sect1>
<title>Implementation</title>
<sect2>
<title>System Startup</title>
<para>If everything goes well, the virtual console display should look
similar to the following example:</para>
<para><screen>Connected to tty1 at 38400 bps.
gnu-linux login:</screen></para>
</sect2>
<sect2>
<title>Add a new user to the system</title>
<para>Log in as root.</para>
<para>Create a new, unprivileged user and new group by appending a line
to the <filename>/etc/passwd</filename> and
<filename>/etc/group</filename> files, respectively. Be sure to use a
double greater-than (&gt;&gt;) to avoid accidentally overwriting the
files.</para>
<para><programlisting><prompt>bash#</prompt> echo "floyd::501:500:User:/home/floyd:/bin/sh" &gt;&gt;/etc/passwd
<prompt>bash#</prompt> echo "users::500:" &gt;&gt;/etc/group
<prompt>bash#</prompt> mkdir /home/floyd
<prompt>bash#</prompt> chown floyd.users /home/floyd
<prompt>bash#</prompt> chmod 700 /home/floyd</programlisting></para>
</sect2>
<sect2>
<title>Test the new user's ability to use the system</title>
<para>Switch to virtual terminal tty2 by pressing
<keycap>ALT</keycap>+<keycap>F2</keycap>.</para>
<para>Log in as floyd.</para>
<para>Try the following commands and verify that they work.</para>
<para><programlisting><prompt>bash$</prompt> pwd
<prompt>bash$</prompt> ls -l /
<prompt>bash$</prompt> cat /etc/passwd</programlisting></para>
<para>Try the following commands and verify that they do not
work.</para>
<para><programlisting><prompt>bash$</prompt> ls /root
<prompt>bash$</prompt> /sbin/shutdown -h now
<prompt>bash$</prompt> su -</programlisting></para>
</sect2>
<sect2>
<title>System shutdown</title>
<para>Switch back to tty1 where root is logged in.</para>
<para><programlisting><prompt>bash#</prompt> shutdown -h now</programlisting></para>
</sect2>
</sect1>
</chapter>