shithub: 9intro

ref: 87288afa5ac476efb3ef1ed40df658427339f13e
dir: /ch14.ms/

View raw version
.so tmacs
.BC 14 "Security
.BS 2 "Secure systems
.LP 
.ix "security
.ix "secure system
Security is a topic that would require a book on its own. Here we just show
the abstractions and services provided by Plan 9 to secure the computer system.
But in any case you should keep in mind that the only secure system is one
that is powered down (and also kept under a lock!). As long as the system can
perform tasks, there is a risk that some attacker convinces the system to do
something that it should not legitimately do.
.PP
.ix "stand-alone machine
.ix "laptop computer
In general, there is a tradeoff between security and convenience. For example,
a stand-alone Plan 9 machine like a laptop that is not connected to the network
does not ask for a password to let you use it. Thus, any person that gets the
laptop may power it up and use it. However,
you do not have to type a password
to use it, which is more convenient. If, on the contrary,
your laptop requires a password to be used, typing the password would be
an inconvenience. Nevertheless,
you might think that this makes the laptop more secure because
it requires to know a password just to use it.
.PP
.ix "malicious person
.ix "evil
.ix "password
By the way, this is not true because as long as a malicious person has your
laptop in his or her hands, the laptop will be broken into and the only question is
how much time and effort it will require to do so. So, using a password to protect
the laptop would be given a false feeling that the system is secure. Furthermore,
although it is common for laptops that might be used on its own, terminals in
Plan 9 are
.I not
.ix "local storage
supposed to have local storage nor any other local resource to protect! A Plan 9
terminal is just a machine to connect to the rest of services in the network.
.PP
What does
.I security
mean?
It depends. For example, the dump in the file server protects your files
from accidental removals or other errors. At least, it protects them in the sense
that you may still access a copy of the entire file tree, as it was yesterday, even
if you lose today's files. Furthermore, because old files kept in disk will never be
overwritten by the file server once they are in the dump, it is very unlikely that a
bug or a software problem will corrupt them. The dump, like other backup tools,
is preserving the
.B integrity
of your data (of your files). This is also part of the security provided by the computing
system. In any case, it is common to understand security in a computer as the
feature that prevents both
.ix "authorized access
.IP 1
unauthorized use of the system (e.g., running programs), and
.IP 2
unauthorized access to data in the system (e.g., reading or modifying files).
.LP
We will focus on security understood in this way, that is, as something to
determine who can do which operations to which objects in the system.
But keep in mind that security is a much wider subject.
.PP
We have already seen several abstractions that have to do with security, understood
this way. First, the persons who can perform actions on things in the computer system
are represented by
.B users .
.ix user
A user is represented in the system by a user name, as you saw. Users rely on
networked
.B machines
or systems to do things in the computing system. 
Machines execute programs. Indeed, the only way for a user to do something on a
machine is to execute a program (or to use one already running).
Protecting the system to permit using it only to
authorized users means just protecting machines so that only authorized users
may convince already
running processes to do things for them. Things like, for example,
running new programs and reading and writing files.
.ix "server process
.PP
In Plan 9, some of the machines are terminals for the users. Other machines
are CPU servers that accept connections from other machines to execute
commands on them. Also, you have one or more file servers, that are machines
whose solely purpose is providing files by running programs similar to the one we
developed in the previous chapter. 
Most (if not
all) the objects in the computer system are represented by files. Thus, the objects
that must be protected by the system are files. Protecting access to files means
deciding if a particular process (acting on behalf of a user) may or may not do
a particular operation on a file.
.BS 2 "The local machine
.LP
.ix "terminal
You know that there are many machines involved in your computing system. But
let's start by considering just the one you are using, or, in general, a single machine.
.PP
A user may execute
commands in a terminal, and use any of its devices,
by booting it and supplying a user name. Terminals are not supposed to keep
state (local storage) in Plan 9 and so there is no state to protect. Also, terminals
are not supposed to export their devices to the network, by listening to network
calls made to access them. This means that nobody should be able to access
a terminal, but for the user who brought it into operation.
Also,
a terminal
is a
.B "single-user
machine. It is not meant to be shared by more than one user. Computers are cheap
these days. 
.PP
How is your terminal secured? The local machine is protected merely
by identifying
the user who is using it.
.B Identification
is one of the things needed to secure a
system. Plan 9 must know who is trying to do something, before deciding if that action
is allowed or not. In Plan 9, the user who switched on the machine is 
called the machine
owner and allowed
.ix "machine owner
to do anything to the machine. This applies not just for terminals, but for any other
Plan 9 machine as well.
.PP
The console device,
.I cons (3),
provides several files that identify both
the machine and its owner. The file
.CW /dev/hostowner
names the user who owns the machine, and
.CW /dev/sysname
names the machine itself.
.P1
; !!cat /dev/hostowner
nemo; 
; cat /dev/sysname
nautilus; 
.P2
.LP
.ix [/dev/hostowner]
.ix [/dev/sysname]
It may be a surprise, but the machine name is irrelevant for security purposes.
Only the host owner is relevant. This terminal trusts that
the user who owns it is
.CW nemo ,
only because one user typed
.CW nemo
when asked for the user name during the booting of the machine. That is all that
matters for this machine. Initially,
Plan 9 created a boot process,
described in
.I boot (8).
Besides doing other things, it asked for a user name and wrote
.CW /dev/hostowner .
But note
that in our example it might happen that the user was not actually
.CW nemo !
For the local machine, it does not matter.
.PP
Deciding who is able to do what is called
.B authorization .
Authorization for the host owner is automatic. The kernel is programmed so that
the machine owner is authorized to do many things. For example, ownership
of console and other devices is given to the host owner.
.P1
.ps -2
; ps | sed 4q
nemo              1    0:00   0:00     1276K Await    bns
nemo              2    0:58   0:00        0K Wakeme   genrandom
nemo              3    0:00   0:00        0K Wakeme   alarm
nemo              5    0:00   0:00        0K Wakeme   rxmitproc
; ls -l '#c'
--rw-rw-r-- c 0 nemo nemo 24 May 23 17:44 '#c/bintime'
--rw-rw---- c 0 nemo nemo  0 May 23 17:44 '#c/cons'
---w--w---- c 0 nemo nemo  0 May 23 17:44 '#c/consctl'
--r--r--r-- c 0 nemo nemo 72 May 23 17:44 '#c/cputime'
--r--r--r-- c 0 nemo nemo  0 May 23 17:44 '#c/drivers'
.I ...
.ps +2
.P2
.LP
This can be double checked by changing the host owner, which is usually a bad idea.
.P1
; echo -n pepe >/dev/hostowner	\fRwe set a new host owner...\fP
; ls -l '#c'
--rw-rw-r-- c 0 pepe pepe 24 May 23 17:44 '#c/bintime'
--rw-rw---- c 0 pepe pepe  0 May 23 17:44 '#c/cons'
---w--w---- c 0 pepe pepe  0 May 23 17:44 '#c/consctl'
.I ...
; echo -n nemo >/dev/hostowner	\fR...and now restore the original one\fP
.P2
.LP
The host owner can do things like adjusting permissions
for files in
.CW /proc ,
which are owned by him. There is nothing that prevents this user from
adding permissions to post notes, for example, to kill processes.
.P1
; ls -l /proc/$pid/note
--rw-r----- p 0 nemo nemo   0 May 23 17:44 /proc/1235/note
; chmod a+w /proc/$pid/note
; ls -l /proc/$pid/note
--rw-rw--w- p 0 nemo nemo 0 May 23 17:44 /proc/1235/note
.P2
.LP
The truth is that users do not exist. For the system, processes are the ones
that may perform actions. There is no such thing as a human. For example,
the human using the window system is represented by the user name of the
process(es) implementing the window system. Therefore,
each process is entitled to a user, for identification purposes. 
In a
terminal, all the processes are usually entitled to the host owner. But how can
this happen?
.PP
.ix booting
.ix [boot]
What happens is that the initial process,
.CW boot
was initially running on the name of the user
.CW none ,
which represents an unknown user. 
After a user name was given to
.CW boot ,
while booting the terminal,
it wrote such user name to
.CW /dev/user
and, from there on, the boot process was running on
the name of
.CW nemo .
The file
.CW /dev/user
.ix [/dev/user]
.ix "user name
.ix "uid
provides the interface for obtaining and changing the user name for the
current process (for the one reading or writing the file).
The user name can only be set once, initially. From there on, the user name can only
be read but not changed. For example, the following happens when using the user name for our shell.
.P1
; cat /dev/user
nemo; 
; echo -n pepe >/dev/user
echo: write error: permission denied
.P2
.LP
Child processes inherit the user name from their parents. So, all the processes in
your terminal are very likely to be owned by you, because they all descend from the
boot process, that changed its ownership to your user name.
.PP
.ix kernel
It is important for you to notice that
.I only
the local machine trusts this.
You are perfectly free to change the kernel in your terminal to do weird things like changing
.CW /dev/user .
Other machines do not trust this information at all. As a result,
running a custom made kernel
just to break into the system would only break into the terminal running that
kernel, and not into other machines.
.PP
This does not happen on other systems. For example, UNIX was made when a
computing system was just a single machine. Networks came later and it was
considered very unlikely that a user could own a machine, attach it to the network,
and run a fake kernel just to break into the system. The result is that most UNIX
machines tend to trust the users responsible for the kernels at different machines
within the same organization. Needless to say that this is a severe security problem.
.BS 2 "Distributed security and authentication
.LP
We have seen that a terminal is secured just by not sharing it. It trusts whoever
boots it. This allows you to run processes in your terminal and use its devices.
However, the terminal needs files to do anything. For example, unless you have
a binary file you cannot execute a new program. There are some programs compiled
into the kernel, kept at
.CW /boot ,
.ix [/boot]
just to get in touch with the file server machine, but that does not suffice to let the
user do any useful work.
.PP
.ix "9P security
Files are provided by file server programs, like the ones we have seen before.
Each file server is responsible for securing its own files. Therefore, there is no
such thing as an account in Plan 9. Strictly speaking, each file server has a list
of user (and group) names known to it, and is responsible for deciding if a user at the other
end of a 9P connection is allowed to do something on a file or not.
.PP
Each file server has some mechanism to open accounts and authorize users. How to do
this is highly dependent on the particular file server used. For
example, each
.CW fossil
has a file
.CW /adm/users
that lists users known to it. Any user that wants to mount a particular
.CW fossil
file server must be listed in the
.CW /adm/users
file kept within that
.CW fossil .
My file server knows me because its administrator included
.CW nemo
in its users file.
.P1
; grep '^nemo' /adm/users
nemo:nemo:nemo:
.P2
.LP
In this case, the fossil administrator used the
.CW uname
and
.CW users
commands in the fossil console to create my user in that file server.
.P1
main: !!uname nemo nemo	\fRadd the user nemo\fP
main: !!users -w		\fRand update the /adm/users file in disk\fP
.P2
.ix "new user
.ix "account
.LP
But to use other file servers I need other accounts. One per file server.
For each file server program its manual page must provide some help regarding how
to let it know which user names exist.
.PP
Note that a user name in a file
server is only meaningful to that file server. Different file servers may have different
lists of users. Within a single organization, it is customary to have a central, main,
file server and to use its
.CW /adm/users
file to initialize the set of users for other secondary file servers also installed.
This is how users are
.I authorized
to use file servers.
.PP
Besides, a file server must also
.I identify
.ix identity
the user who is using it. This is done using
9P.
When a process mounts a file server in its name space, the user name is sent in the
.CW Tattach
.ix [Tattach]
request. As you know, the attach operation gives a handle, a fid, to the client
attaching to the file system.
This permits the file server to identify the user responsible for operations requested
on that fid. When new fids are obtained by walking the file tree, the file server
keeps track of which user is responsible for which fids.
.PP
.B "Access control" ,
that is,
.ix "permitted operation
deciding if a particular operation is to be allowed or not, is performed by the file
server when a user opens a file, walks a directory, and tries to modify its entries
(including creating and removing files). When a process calls
.CW open
on a file,
the system sends a
.CW Topen
.ix [Topen]
.ix "permission check
request to the file server providing the file. At this point, the file server takes the
user name responsible for the request and decides whether to grant access or not.
You know, from the first chapter, that this is done using per-file
.B "access control lists" ,
that determine which operations can be performed on which file.
Once a file has been open for a particular access mode (reading, writing, or
both), no further access control check is made. The file descriptor, (or the fid
for that matter) behaves like a
.I capability
(a key) that allows the holder to perform file operations consistent with the open
mode.
.PP
These are all the elements involved in securing access to files, but for an
important one. It is
necessary to determine if the user, as identified for a file server, is who he or she claims
to be. Users can lie! This operation is called
.B authentication .
Authenticating a user means just obtaining some proof that the user is indeed
the one identified by the user name. Most of the machinery
provided for security by Plan 9 is there just to authenticate users.
.ix "proof of~identity
.PP
.ix "shared secret
And here comes the problem. In general, the way a program has to convince
another of something is to have a secret also known to the other. For example,
when an account is open for a user in a Plan 9 environment, the user must go
near the console of a server machine and type a password, a secret. The same
secret is later typed by the same user at a terminal. Because the terminal and
the server machine share the same secret, the sever can determine that the user
is indeed who typed the password while opening the account. Well, indeed, the
server does not know if the password is also known by another user, but the
server assumes this would not happen.
.PP
Authentication is complex because it must work without trusting the network.
There are many different protocols consisting on messages exchanged in a
particular way to allow an end of a connection to authenticate the other end,
without permitting any evil process spying or intercepting network messages
to obtain unauthorized access. Once more, we do not cover this subject in this
book. The important point is that there are multiple authentication
protocols, and that there is an interface provided by the system for this purpose.
.PP
The
.CW mount
.ix [mount]
system call receives two file descriptors, and not just one (even though a file
descriptor for a connection to a file server is all we need to speak 9P with it).
.P1
.ps -2
; sig mount
	int mount(int fd, int afd, char *old, int flag, char *aname)
.ps +2
.P2
.LP
The
.CW fd
descriptor is the connection to the file server. The second one,
.CW afd ,
is called an
.I "authentication file descriptor" ,
.ix "authentication file
.ix [afd]
used to authenticate to the file server. Before calling
.CW mount ,
a process calls
.CW fauth
.ix [fauth]
to authenticate its user to a file server at the other end of a connection.
.P1
; sig fauth
	int fauth(int fd, char *aname)
.P2
.LP
For example, if the file descriptor 12 is connected to a file server,
.P1
afd = fauth(12, "main")
.P2
.LP
obtains an authentication file descriptor for authenticating our user to access
the file tree
.CW main
in the file server. This descriptor is obtained by our system using a
.CW Tauth
.ix [Tauth]
.ix [Rauth]
9P request.
And now comes the hard part. We must negotiate with the file server a particular
authentication protocol to use. Furthermore, we must exchange messages by
reading and writing
.CW afd
according to that protocol, to give proof of our identity to the file server. This is
complex and is never done by hand. Assuming we already made it,
.CW afd
can be given to
.CW mount ,
to prove that we have been already authenticated. For example, like in
.P1
mount(12, afd, "/n/remote", MREPL, "main");
.P2
.LP
In most cases, the library function
.CW amount
does this. So, it would have been the same to do just
.P1
amount(12, "/n/remote", MREPL, "main");
.P2
.LP
instead of calling
.CW fauth ,
.ix "authentication protocol
following an authentication protocol, and calling
.CW mount .
It is easier to let
.CW amount
take care of authentication by itself. In the next section we will show how
this could be.
.PP
For now, the important point is to note how authentication is performed by
exchanging messages between the two processes involved. In this case,
the file server and our client process. The authentication file descriptor obtained
above is just a channel where to speak an authentication protocol, using some sort of
shared secret to convince the other process, nothing else. It permits
keeping the authentication messages apart from 9P.
.PP
If there was only a single server, providing a secret to it for each user would
suffice to authenticate all users in the Plan 9 network. However, there can be
may ones. Furthermore, authentication is used not just to convince file servers.
It is also used to convince other servers providing different services, like
command execution. Instead of having to open an account with the user's secret
for each server, authentication is centralized in, so called,
.B "authentication servers" .
.PP
An authentication server is a machine that runs an authentication server process,
perhaps surprisingly. The idea behind an authentication server is simple. Authentication
is delegated to this server. Instead of sharing a secret, and trusting each other
because of the shared secret, both the client process and the server process trust a
third process, the authentication server. This means that both processes must share
a secret with the third trusted one.
.PP
No matter how many servers there are,
the client only needs one secret, for using the authentication server. Using it, the
client asks the authentication server for
.B tickets
to gain access to servers. Each ticket is a piece of data that is given to a client,
and can be used to convince the server that the client is indeed who it claims to be.
This can be done because the authentication server may use the secret it shares
with the server to encrypt some data in the ticket given to the client. When the client
sends the ticket to the server, the server may know that the ticket was issued by
someone knowing its own secret, i.e., by the authentication server.
.PP
The authentication server in Plan 9 is implemented by the program
.CW authsrv ,
described in
.I auth (8).
.ix [authsrv]
It runs on a machine called the authentication server, as you might guess. In many
cases, this machine may be the same used as the main file server, if it runs such
process as well.
.PP
Things are a little bit more complex, because a user might want to use servers
maintained by different organizations. It would not be reasonable to ask all Plan 9
file servers in the world to share a single authentication server. As a result, machines
are grouped into, so called,
.B "authentication domains" .
An authentication domain is just a name, representing
a group of machines that share an authentication server, i.e., that
are grouped together for authentication purposes. Each Plan 9 machine
belongs to an authentication domain, set by the machine boot process (usually
through the same protocol used to determine the machine's IP address, i.e., DHCP).
.PP
The file
.CW /dev/hostdomain ,
.ix [/dev/hostdomain]
.ix [hostdomain]
.ix [hostowner]
provided by the
.I cons (3)
device, keeps the authentication domain for the machine.
.P1
; cat /dev/hostdomain
dat.escet.urjc.es;
;
.P2
.LP
Regarding authentication, a user is identified not just by the user name (e.g., that in
.CW /dev/hostowner ),
but also by the associated authentication domain. A single user might have different
accounts, for using different servers, within different authentication domains. In many
cases, the same user name is used for all of them. However, a user might have
different user names for each different authentication domain.
.BS 2 "Authentication agents
.LP
In any case, we still have to answer some questions.
How does a client (or a sever) run the authentication protocol? How do
they speak with the authentication server? Where do they keep the secrets? Strictly
speaking, in Plan 9, neither process does any of these tasks!
All the authentication protocols are
implemented by a program called
.CW factotum .
.ix [factotum]
This program is what is known as an
.B "authentication agent" ,
i.e., a helper process to take care of authentication.
A factotum keeps the
secrets
for other processes, and is the only program that knows
how to perform the client or the server side of any
authentication protocol used in Plan 9.
.PP
Factotum keeps
.B keys .
A key is just a secret, along with some information about the secret itself (e.g.,
which protocol is the secret for, which user is the secret for, etc.)
Factotum is indeed a file system, started soon after the the machine boots,
which mounts itself at
.CW /mnt/factotum .
Its interface is provided through the files found there.
.P1
; lc /mnt/factotum
confirm	ctl	log	needkey	proto	rpc
.P2
.LP
The file
.CW ctl
is used to control the set of secrets kept by the factotum. Reading it, reports
the list of keys known (without reporting the actual secrets!)
.P1
.ps -2
; cat /mnt/factotum/ctl
key proto=p9sk1 dom=dat.escet.urjc.es user=nemo !password?
key proto=p9sk1 dom=outside.plan9.bell-labs.com user=nemo !password?
key proto=vnc dom=dat.escet.urjc.es server=aquamar !password?
key proto=pass dom=urjc.es server=orson service=ssh user=nemo !password?
key proto=rsa service=ssh size=1024 ek=10001 n=DE6D279E8B49C9B1F44B
9CA26114005BD2EB1B255A92F42D475B49D333FA4886990DDF17108
FE4237A2FD6E1CB2C040C1F5361F03352DAE67243B62CE2664663B
E0AE1F1933CDF935 !dk? !p? !q? !kp? !kq? !c2?
.ps +2
.P2
Each one of the lines above corresponds to a single key kept by this factotum process,
and starts with
.CW key .
.ix [key]
The last line is so large, that it required four output files in the terminal session reproduced
above.
.PP
The first line shown above corresponds
to the key used to authenticate to file servers using the
P9SK1 authentication protocol (Plan 9 Shared Key, 1st).
.ix [9PSK1]
.ix [9PANY]
.P1
key proto=p9sk1 dom=dat.escet.urjc.es user=nemo !password?
.P2
As you can see, a
key is a series of
.I attribute
and
.I value
pairs. In this key, the attribute
.CW proto
has as value
.CW p9sk1 .
The purpose of this attribute is to identify the protocol that uses this key.
Other attributes depend on the particular authentication protocol for the key. In
P9SK1 keys,
.CW dom
identifies the
.B "authentication domain"
for a key. This is just the name that identifies a set of machines, for organizative
purposes, that share an authentication server. The attribute
.CW user
identifies our user name within that domain. Note that we might have different
P9SK1 keys for different authentication domains, and might have different user
names for them. The attribute
.CW password
.ix password
has as its value a secret, that is not shown by factotum.
.PP
New keys can be added to factotum by writing them to the
.CW ctl
file, using the same syntax. The next command adds a key for using P9SK1, as
the user
.CW nemo ,
for the
.CW foo.com
authentication domain.
.P1
.ps -2
; echo 'key proto=p9sk1 dom=foo.com user=nemo !password=whoknows' \e
;; >/mnt/factotum/ctl
; grep foo.com /mnt/factotum/ctl
proto=p9sk1 dom=foo.com user=nemo !password?
;
.ps +2
.P2
.LP
The value for the attribute
.CW password
is the shared secret used to authenticate the user
.CW nemo ,
by using the authentication server for the
.CW foo.com
domain.
Because the attribute name
was prefixed with a
.CW !
sign,
.CW factotum
understands that it is an important secret, not to be shown while reading
.CW ctl .
In general, factotum does its best to avoid disclosing secrets. It keeps them for
itself, for use when speaking the authentication protocols involved. Look what
happens below.
.P1
.ps -2
; ps | grep factotum
nemo              6    0:00   0:00      268K Pread    factotum
; acid 6
/proc/6/text:386 plan 9 executable

<stdin>:1: (error) setproc: open /proc/6/mem: permission denied
/sys/lib/acid/port
/sys/lib/acid/386
no symbol information
acid:
.ps +2
.P2
.LP
.ix "debug protection
You cannot debug factotum! It protects its memory, to prevent any process from
reading its memory and obtaining the keys it maintains. This can be done to
any process by writing the
string
.CW private
.ix "private memory
to the process
.CW ctl
file.
That is what factotum did to itself to keep its memory
unreadable from outside. In the same way, factotum wrote
.CW noswap
.ix [noswap]
to its process control file, to ask Plan 9 not to swap its memory out to disk when running
out of physical memory.
.PP
It is now clear how to add keys to factotum, but how can a process authenticate?
A process can authenticate to another peer process
by relying messages between its factotum and the other peer. As
figure [[!relays messages authenticate!]] shows, during authentication, a client
process would simply behave as an intermediary between its factotum and
the server. When its factotum asks the process so send a message to the other
end, it does so. When it asks the process to receive a message from the other end,
and give it to it, the process obeys. In the same way, a server process relays
messages to and from its own factotum to authenticate clients.
.LS
.PS
right
circlerad=.35
F: circle "factotum"
arrow <-> 
C1: circle "client" "process"
arrow <-> right 1.2 "network" "connection"
circle "server" "process"
arrow <-> 
circle "factotum"
spline <-> from F.se down right .5 then right .5
circle "client" "process"
arrow <-> right 1.2 "network" "connection"
circle "server" "process"
reset
.PE
.LE F A process relays messages to and from its \f(CWfactotum\fP to authenticate.
.PP
The protocol is only understood by the factotum. So, if both the client and the server
have a factotum, it is both factotums the ones speaking the authentication protocol.
The only peculiarity is
that messages exchanged for authentication between both factotums
pass through the client and
the server processes, which behave just as relays. As the figure shows, different
servers might have different factotums. The same happens for clients. And of course,
more than one process may use the same factotum. Which factotum is used is determined
by which factotum is mounted at
.CW /mnt/factotum .
.PP
For example, executing a new
.CW factotum
mounts another factotum at
.CW /mnt/factotum ,
isolating the processes that from now on try to authenticate in our name space.
.P1
; auth/factotum
; cat /mnt/factotum/ctl
;			\fIThis one has no keys!\fP
.P2
.LP
There is another important thing to note. A process may use a
factotum even if the other peer does not. For example, the lower server shown in
the figure 14.1 does not use a factotum and is implementing the authentication protocol
on its own. As long as a process speaks properly
the necessary authentication protocol, it does not matter if it is the one
actually speaking, or just a relay for a factotum.
.PP
The
.I connection
kept between a process and its factotum during an authentication session is
provided by the
.CW /mnt/factotum/rpc
file. This file provides a distinct channel each time it is open. It is named
.CW rpc
.ix "[rpc] file
because the process performs RPCs to the factotum by writing requests
through this file (and reading replies from factotum),
to ask what it should do and rely messages.
.PP
The
.I auth (2)
.ix "[auth] library
library provides authentication tools that work along with factotum. Among
other things, it includes a function called
.CW auth_proxy
.ix [auth_proxy]
.ix relying
that takes care of authentication by relying messages between the
factotum reached through
.CW /mnt/factotum/ctl
and the other end of a connection. It returns a data structure with
some authentication information.
.P1
.ps -2
; sig auth_proxy
    AuthInfo* auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...);
.ps +2
.P2
.LP
To show how to use this function, the following program mounts a file server and performs
any authentication necessary to gain access to the server's file tree. The
.I auth
library provides
.CW amount
.ix [amount]
to do this. Instead of using it, the program implements its own version for
this function.
.so progs/amount.c.ms
.ix [amount.c]
.LP
The first argument for the program is a file used as a connection to
the server. The program opens it and calls its own
.CW authmount
function. This function returns the
.CW Authinfo
.ix [Authinfo]
.ix "authentication information
obtained by calling
.CW auth_proxy
using its last parameter, and our program prints some diagnostics about such
structure before calling
.CW auth_freeAI
.ix [auth_freeAI]
to release it.
.PP
The important part of this program is the implementation for
.CW authmount ,
similar to that of
.CW amount
but for returning the
.CW Authinfo
to the caller.
.P1
.ps -2
int
authmount(int fd, char *mntpt, int flags, char *aname, AuthInfo** aip)
{
	int afd, r;

	afd = fauth(fd, aname);
	if (afd < 0){
		*aip = nil;
		fprint(2, "fauth: %r\en");
		return mount(fd, afd, mntpt, flags, aname);
	}
.ps +2
.P2
.P1
.ps -2
	*aip = auth_proxy(afd, amount_getkey,
		"proto=p9any role=client");
	if (*aip == nil)
		return -1;
.ps +2
.P2
.P1
.ps -2
	r = mount(fd, afd, mntpt, flags, aname);
	close(afd);
	if (r < 0){
		auth_freeAI(*aip);
		*aip = nil;
	}
	return r;
}
.ps +2
.P2
.LP
The function is used by a client process to authenticate to a (file) server
process. First, the client process must obtain a connection to the server
and pass its descriptor in
.CW fd .
Before authentication takes place, the function calls
.CW fauth
to obtain a file descriptor that can be used to send and receive
messages for authenticating with the server, and keeps it in
.CW afd .
.ix [afd]
In general, clients may use the initial connection to a server
to authenticate. However, for a 9P file server, you know that a
separate (authentication) descriptor is required instead.
.PP
In any case, the point is that calling
.CW auth_proxy
with a descriptor to reach the server process,
.CW afd
in this case,
suffices to authenticate our user to the server.
.CW Auth_proxy
opens
.CW /mnt/factotum/ctl ,
and loops asking factotum what to do, by doing RPCs through this
.CW ctl
file. If factotum says so,
.CW auth_proxy
reads a message from the peer, by reading
.CW afd ,
and writes it to factotum (to the
.CW ctl
file). If factotum, instead, asks for a message to be sent to the peer,
.CW auth_proxy
takes the message from the
.CW ctl
file and writes it to
.CW afd .
.PP
.ix "role
Which protocol to speak, and which role to take in that protocol (client or
server), is determined by the last parameters given to
.CW auth_proxy .
Such parameters are similar to the arguments for
.CW print ,
to permit may different invocations depending on the program needs.
In our case, we gave just the format string
.P1
"proto=p9any role=client"
.P2
.LP
But passing more arguments in the style of
.CW print
can be done, for example, to specify the user for the key, like here:
.P1
char* user;
\fI...\fP
auth_proxy(afd, getkey, "proto=p9any role=client user=%s", user);
.P2
.LP
Such string is given to factotum, which matches it against the keys
it keeps. It is used as a template to select the key (and protocol)
to use. In this case, any key matching the
.CW p9any
protocol can be used, using the role of a client. The
.CW p9any
protocol is not exactly a protocol, but a way to say that we
do not care about which particular Plan 9 authentication protocol is used.
When this
.ix "meta-protocol
.I meta-protocol
is used, both the client and the server negotiate the actual authentication
protocol used, like for example, P9SK1.
.PP
Once
.CW auth_proxy
completes, it may have succeeded authenticating the user or not. If it does,
it returns an
.CW Authinfo
structure, which is a data structure that contains authentication information
returned from factotum.
.P1
typedef struct AuthInfo AuthInfo;
struct AuthInfo
{
	char	*cuid;		/* caller id */
	char	*suid;		/* server id */
	char	*cap;		/* capability */
	int	nsecret;	/* length of secret */
	uchar	*secret;	/* secret */
};
.P2
.LP
For example, this is what results from using
.CW 8.amount
to mount several file servers. First, we start a new
.CW ramfs ,
which does not require any authentication, and
mount it.
.P1
; ramfs -s ram
; 8.amount /srv/ram /n/ram ''
fauth: authentication not required
no auth information obtained
.P2
.LP
The call to
.CW fauth
(which sends a
.CW Tauth
request to the server) fails with the error
.CW "authentication not required" .
So, the function
.CW authmount
simply called
.CW mount
using
.CW -1
as
.CW afd ,
after printing a diagnostic for us to see. As a result, no
.CW AuthInfo
is obtained in this case.
.PP
Second, we use
.CW 8.amount
to mount our main file server,
wich does require authentication (the key for authenticating to the server
using P9SK1 was known to the factotum used).
.P1
; 8.amount /srv/tcp!whale!9fs /n/whale main/archive
client uid: nemo
server uid: nemo
.P2
.LP
In this case,
.CW auth_proxy
was called and could authenticate using
.CW factotum .
The
.CW AuthInfo
structure returned contains
.CW nemo
in its
.CW cuid
.ix "client uid
field (client uid). That is the actual user id we are using at our terminal.
It also contains
.CW nemo
in its
.CW suid
.ix "server uid
field (server uid). That is the user id as known to the server. In our case, both
user names were the same, but they could differ if I was given a different user
name for the account at
.CW whale .
.PP
In most cases, a client is only interested in knowing if it could authenticate or not.
Like in our example (and in
.CW amount ),
most clients would just call
.CW auth_freeAI ,
to release the
.CW AuthInfo
structure, after a successful authentication. For server programs, things may be
different. They might employ the information returned from factotum as we will
see later.
.PP
But what would happen when
.CW factotum
does not know the key needed to authenticate to the server?
In the call to
.CW auth_proxy ,
the function
.CW amount_getkey
.ix "key reading
.ix [amount_getkey]
was given as a parameter. This function is provided by the
.I auth (2)
library and is used to ask the user for a key when
factotum does not have the key needed for the protocol chosen. For example,
below we try to mount the file server
.CW whale ,
in the window where we started a new factotum, which starts with no keys.
.P1
; auth/factotum
; cat /mnt/factotum/ctl
;			\fIThis one has no keys!\fP
; 8.amount /srv/tcp!whale!9fs /n/whale main/archive

!Adding key: dom=dat.escet.urjc.es proto=p9sk1
user[nemo]: 	\fI we pressed return\fP
password: 	\fI we typed the password here\fP
!
client uid: nemo
server uid: nemo
.P2
.LP
Here,
.CW auth_proxy
called the function
.CW amount_getkey ,
given as a parameter, to ask for a key to mount
.CW whale .
At this point, the message starting
.ix "adding key
.CW "!Adding key" ...
was printed, and we were asked for a user name and password for the P9SK1
protocol within the
.CW dat.escet.urjc.es
authentication domain. That information
was given to factotum, to install a new key,
and authentication could proceed. After that, factotum has the new key for
use in any future authentication that requires it.
.P1
; cat /mnt/factotum/ctl
key proto=p9sk1 dom=dat.escet.urjc.es user=nemo !password?
.P2
.LP
We will never be prompted for
that key again as long as we use this factotum.
.BS 2 "Secure servers
.PP
.ix "handling authentication
.ix "secure server
Handling authentication in a server can be done in a similar way. In general,
the server calls
.CW auth_proxy
to relay messages between the client and
.CW factotum .
The only difference is that the role is now
.CW server ,
instead of
.CW client .
.PP
For 9P servers, the
.I 9p (2)
library provides helper routines that handle authentication. A 9P
server that implements authentication for its clients must create (fake)
authentication files in response to
.CW Tauth
.ix [Tauth]
requests. Such files exist only in the protocol, and not in the file tree served.
They are just a channel to exchange authentication messages by using
.CW read
and
.CW write
in the client.
.PP
To secure our
.CW semfs
file server (developed in a previous chapter), we first provide a key template
in the
.CW Srv
structure that defines the implementation for the server. The
function
.CW auth9p
provided by the library can be used as the implementation for the
.CW auth
operation in
.CW Srv .
It allocates authentication files, flagging them by setting
.CW QTAUTH
.ix [QTAUTH]
.ix "authentication file
in their
.CW Qid.types.
.P1
static Srv sfs=
{
	.auth	=	auth9p,
	.attach =	fsattach,
	.create	=	fscreate,
	.remove =	fsremove,
	.read	=	fsread,
	.write	=	fswrite,
	.walk1	=	fswalk1,
	.clone	=	fsclone,
	.stat	=	fsstat,
	.destroyfid=	freefid,
	.keyspec =	"proto=p9any role=server"
};
.P2
.LP
Because there are authentication files, the implementation of
.CW fsread
and
.CW fswrite
must behave differently when the file read/written is an authentication file.
In this case, the data must be relayed to factotum and not to a file served.
The new implementation for
.CW fsread
would be as follows.
.P1
static void
fsread(Req* r)
{
	Fid*	fid;
	Qid	q;
	Sem*	s;
	char	nl[2] = "\n";

	fid = r->fid;
	q = fid->qid;
	if (q.type&QTAUTH){
		authread(r);
		return;
	}
	\fI...everything else as before...\fP
}
.P2
.LP
It calls the helper function
.CW authread ,
.ix [authread]
.ix [auth9p]
provided by
.CW lib9p ,
to handle reads from authentication files (i.e., to obtain data from the underlying
factotum to be sent to the client).
In the same way,
.CW fswrite
must include
.P1
if (q.type&QTAUTH){
	authwrite(r);
	return;
}
.P2
.LP
to take a different course of action for writes to authentication files. The
library function
.CW authwrite
.ix [authwrite]
takes care of writes for such files.
.PP
Fids for authentication files keep state to talk to the underlying factotum. The
function
.CW authdestroy
.ix [authdestroy]
.ix [destroyfid]
must be called
for fids that refer to authentication files. This means that we must change the
function
.CW freefid ,
which we used to release the semaphore structure for a fid, to release
resources for authentication fids.
.P1
static void
freefid(Fid* fid)
{
	Sem*	s;

	if (fid->qid.type&QTAUTH)
		authdestroy(fid);
	else {
		s = fid->aux;
		fid->aux = nil;
		closesem(s);
	}
}
.P2
.LP
The purpose of the entire authentication process is to demonstrate in the
.CW Tattach
request that the user was who he/she claimed to be. So,
.CW fstattach
must be changed as well. The library function
.CW authattach
makes sure that the user is authenticated. When it returns
.CW -1 ,
to signal a failure,
it has already responded with an error to the caller, and the server should
not respond. Otherwise, the user has been authenticated.
.P1
static void
fsattach(Req* r)
{
	if (authattach(r) < 0)
		return;
	r->fid->qid = (Qid){0,0,QTDIR};
	r->ofcall.qid = r->fid->qid;
	respond(r, nil);
}
.P2
.LP
.ix "message dump
After compiling the new program into
.CW 8.asemfs ,
we can try it.
As you may remember,
.CW 8.asemfs
mounts itself at
.CW /mnt/sem
(the parent process spawns a child to speak 9P, and mounts it). Using the flag
.CW -D ,
we asked for a dump of 9P messages to see what happens.
First, we execute it while using a factotum that has no keys.
.P1
.ps -2
; 8.asemfs -D
<-11- Tversion tag 65535 msize 8216 version '9P2000'
-11-> Rversion tag 65535 msize 8216 version '9P2000'
<-11- Tauth tag 10 afid 485 uname nemo aname 
-11-> Rauth tag 10 qid (8000000000000001 0 A)
<-11- Tread tag 10 fid 485 offset 0 count 2048
-11-> Rerror tag 10 ename authrpc botch
<-11- Tattach tag 10 fid 487 afid 485 uname nemo aname 
-11-> Rerror tag 10 ename authrpc botch
<-11- Tclunk tag 10 fid 485
-11-> Rclunk tag 10
8.asemfs: mount /mnt/sem: authrpc botch
;
.ps +2
.P2
.LP
This time, the server replied to
.CW Tauth
with an
.CW Rauth
message, and not with an
.CW Rerror
to indicate that authentication was not required. Because of this, the
.CW amount
call made by the client (the parent process) calls
.CW auth_proxy
to authenticate the user to the server.
.PP
You may see how the poor client
tries to read the authentication fid (485), to obtain a message from the
server as part of the authentication protocol. It fails. The server's factotum
informed with an
.CW "authrpc botch"
error that it could not authenticate. This is not a surprise, because the factotum
for the server had no keys. The optimistic (but still poor) client tried to attach
to the server, anyway. The server refused this time, because the client was not
authenticated. Things are different when the server's factotum is equipped with
a key for P9SK1.
.P1
.ps -2
; 8.asemfs -D
<-11- Tversion tag 65535 msize 8216 version '9P2000'
-11-> Rversion tag 65535 msize 8216 version '9P2000'
<-11- Tauth tag 10 afid 465 uname nemo aname 
-11-> Rauth tag 10 qid (8000000000000001 0 A)
<-11- Tread tag 10 fid 465 offset 0 count 2048
-11-> Rread tag 10 count 24 '7039736b 31406461 ....'
<-11- Twrite tag 10 fid 465 offset 24 count 24 '7039736b 31206461 ...'
-11-> Rwrite tag 10 count 24
<-11- Twrite tag 10 fid 465 offset 48 count 8 '7501af21 166c2391'
-11-> Rwrite tag 10 count 8
<-11- Tread tag 10 fid 465 offset 56 count 141
-11-> Rread tag 10 count 141 '016e656d 6f000000 ....'
<-11- Twrite tag 10 fid 465 offset 197 count 85 'f63182df 120add32 ...'
-11-> Rwrite tag 10 count 85
<-11- Tread tag 10 fid 465 offset 282 count 13
-11-> Rread tag 10 count 13 '2be8ff3e d96f0f29 ...'
.ps +2
.P2
.P1
.ps -2
<-11- Tattach tag 10 fid 234 afid 465 uname nemo aname 
authenticate nemo/: ok
-11-> Rattach tag 10 qid (0000000000000000 0 d)
<-11- Tclunk tag 10 fid 465
-11-> Rclunk tag 10
.ps +2
.P2
.LP
In this output, you see how the client sends read and write requests, successfully,
to the authentication fid 465. Such operations obtain messages and send them
to the server's factotum, respectively. After a series of messages authenticate the
client using the P9SK1 protocol, the client sends a
.CW Tattach
request providing the authentication file (fid 465) as a proof of identity. The
server accepts the proof, and the client manages to attach to the server. At this point,
the authentication file is no longer useful and is clunked by the client (because its
.CW afid
was closed).
.PP
This was the idea. Both the client and the server managed to speak P9SK1
to authenticate without having a single clue about that authentication protocol.
They just arranged for their factotums to speak the protocol, on their behalf.
.BS 2 "Identity changes
.LP
At this point, despite our efforts, we could ask the question: is the server secure?
In this case,
.CW semfs
does not listen to requests in the network, and authenticates clients. That seems
secure enough. However, there is an important common sense rule in security, called
the
.B "least privilege principle" .
This rule says that a program should have no more rights than needed to perform
its job. The
.CW semfs
file server serves semaphores. But a bug in the program might make it access
files or do any other weird thing. Attackers might exploit this.
.PP
.ix sandboxing
What we can do is to put the server in a sandbox, and remove any privileges
that the user who starts it might have. This can be done by changing our user
to
.ix [none]
.CW none ,
which can always be done for a process by writing
.CW none
to
.CW /dev/user .
Also, we can rebuild the process name space from scratch, for the new user
name, using
.CW newns ,
provided by the
.I auth
library.
This function may be called to become the user
.CW none .
.P1
void
becomenone(void)
{
	int	fd;

	fd = open("#c/user", OWRITE);
	if (fd < 0)
		sysfatal("#c/user: %r");
	if (write(fd, "none", 4) < 0)
		sysfatal("can't become none");
	close(fd);
	newns("none", nil);
}
.P2
The second parameter to
.CW newns
.ix [newns]
names a namespace file, which is
.CW /lib/namespace
.ix [/lib/namespace]
.ix "new namespace
by default.
After modifying our
.CW asemfs
file server to call
.CW becomenone
early in
.CW fstattach ,
we can see the effect.
.P1
.ps -2
; 8.asemfs -s sem
; ps | grep asemfs
nemo           1410    0:00   0:00      204K Pread    8.asemfs
; mount -c /srv/sem /mnt/sem
; ps | grep asemfs
none           1410    0:00   0:00      240K Pread    8.asemfs
.ps +2
.P2
.LP
The first command started
.CW 8.asemfs ,
asking it to post at
.CW /srv/sem
a file descriptor to mount its file tree. As you can see, at this point the
process is owned by the user who started the server, i.e.,
.CW nemo .
The server may potentially access any resource this user could access.
However, after mounting it,
.CW ps
reports that the process is entitled to user
.CW none .
It no longer can access files using
.CW nemo
as its identity. This limits the damage the server can do, due to any bug.
Furthermore, reading
.CW /proc/1410/ns
would report that this process now has a clean namespace, built from the
scratch for the user
.CW none .
Any resource obtained by
.CW nemo ,
by mounting file servers into its namespace, is now unaccessible for this process.
.PP
We could go even further by calling
.CW rfork(RFNOMNT)
.ix "[RFNOMNT] [rfork]~flag
near the end of
.CW becomenone .
.ix "become [none]
This prevents the process from mounting any other resource into its namespace.
It will be confined for life, with almost no privilege.
.PP
In general, for a server, calling a function like
.CW becomenone
would be done early in
.CW main ,
before servicing requests from the network. In our case, we cannot
do this in the main function, because the process that has to belong to
.CW none
is the one implementing the file server. This process is started by
.CW threadpostmountsrv ,
and therefore we must arrange for such a process (and not the parent) to call
.CW becomenone .
We placed the call in
.CW fstattach ,
because the server is not likely to do any damage before a client can mount it.
.PP
Becoming the user
.CW none
was an identity change. In general, this is the only identity change made
by most programs.
In CPU servers it is usual for processes that listen for network requests, like
HTTP servers, to run as none.
.PP
Sometimes, it may be necessary to become a different user, and not just
.CW none .
Consider again CPU servers.
.ix "CPU server
Running on them, there are other server
processes that must execute commands
on behalf of a user. For example, the processes listening for remote command
execution requests must execute commands on behalf of a remote user.
.PP
There is one interesting thing to learn here. Executing new processes for a remote
user can be done perfectly by a server process without changing its user id. After
authenticating a client, a server may just spawn a child process to execute
a command for the remote user. But this works as long as the process for
the remote user does not try to use resources outside the CPU server. As soon
as it tries, for example, to mount a file server, it would need to authenticate and
identify itself using the client user id, and not the user id for the server that
provides remote execution in the CPU server. Of course, in practice, a process
for a remote user is very likely to access resources outside the CPU server and
therefore requires some means to change its user id.
.PP
And there is an even more interesting thing to see now. When you connect to
a CPU server to execute a command on it, the name space from your terminal
is exported to the server process that runs the command in the CPU server.
We saw this earlier. The name space is exported using the connection
to the CPU server, after authentication has been performed. As a result, the
process started for you in the CPU server does
.I not
require to change its ownership to use any of the files re-exported from your
terminal for it. Is has all of them in its name space. Of course, mounting something
while running in a CPU server is a different thing, and requires an identity change
as you now know.
.ix "identity change
.PP
Because speaking for others (as a result of changing the user identity) is
potentially very dangerous. The authentication server takes precautions to
allow only certain users to speak for others within its authentication domain.
The file
.CW /lib/ndb/auth
.ix [/lib/ndb/auth]
.ix "speak~for
lists which users may speak for which others. Usually, CPU servers are started by
fake users whose sole purpose is to boot such servers. Such users are usually
the only ones allowed to speak for other users, to prevent a user impersonating
as another.
.PP
A notable example of a tool that requires identity changes is
.CW auth/cron .
.ix [cron]
This command executes commands periodically, as mandated by each user, on a
CPU server chosen by each user. Each user has a file
.CW /cron/$user/cron
that lists periodic commands. For example, this is the
.CW cron
file for
.CW nemo .
.P1
.ps -1
; cat /cron/nemo/cron
#m h dm m dw host
0 0 * *  * whale chmod +t /mail/box/nemo/spam
0 0 * * * aquamar /usr/web/cursos/mkcursos
.ps +1
.P2
.LP
Each line describes a periodic job. It contains the times when to execute it,
using fields to select which minute, hour, day of month, month, and day of week.
In this case, both jobs are executed at midnight. The first job is to be executed
at the CPU server
.CW whale ,
and the second one is to be executed at the CPU server
.CW aquamar .
Each job is described by the command found last in each line.
.PP
The point is that for commands like
.CW cron
and
.CW cpu
to work, it is necessary to change the identity of the processes that
run in the CPU server on behalf of a user. As you know, initially, all processes
in the CPU server are entitled to the machine owner (but for perhaps a few
that decided to switch to the user
.CW none ).
However, some of these processes might want to change the user id.
.PP
This can be done by using the
.I cap (3)
.ix "capability device
device. This device provides
.B capabilities
to change ownership. A capability is just a key that allows a process to do something.
In this case, a capability may be used to convince the kernel to change the
user id for a process.
.PP
As you know, the host owner is very powerful within the local machine.
A process running on the name of the host owner may permit any other process
in the machine to change its user identity by means of the files
.CW /dev/caphash
and
.CW /dev/capuse
provided by
.I cap .
.PP
The idea is as follows. When a user authenticates to a server,
the factotum
for the server process, if running on the name of the host owner, may
help the server to change its identity to that of the user who authenticated.
After a successful authentication, the function
.CW auth_proxy
returns an
.CW AuthInfo
.ix [AuthInfo]
structure with authentication information for the user. This happens also for
a server process, when it uses
.CW auth_proxy
(i.e.,
.CW factotum )
to authenticate the client. Besides the
.CW cuid
and
.CW suid
fields, with the user ids for the client and the server, an
.CW AuthInfo
contains a
.CW cap
field with some data that is a capability for changing the user id to that of
the user authenticated.
.PP
What happens is that
.I cap (3)
trusts
.CW factotum ,
because it runs on the name of the host owner. Besides returning the
.CW AuthInfo
to the user,
.CW factotum
used the
.I cap
device to ask the kernel to allow any process holding the data in
.CW Authinfo.cap
to change its id to the user who authenticated. It did so by writing a hash
of the capability to
.CW /dev/caphash .
Later, our server process may write to
.CW /dev/capuse
the capability in
.CW Authinfo.cap ,
and change its identity.
.PP
The function
.CW auth_chuid ,
.ix [auth_chuid]
.ix "identity change
.ix "uid change
from the
.I auth
library, takes care of using the capability in
.CW AuthInfo
for changing the user id. Also, as an extra precaution, it builds a new name
space according to the name space file supplied, or
.CW /lib/namespace
if none is given. The following code might be used by a server program to
authenticate a client and then changing its user id to continue execution on the
user's name.
.P1
int	fd;	// file descriptor to the client process
AuthInfo*ai;
 \fI...\fP
ai = auth_proxy(fd, getkey, keyspec);
if (ai == nil)
	sysfatal("authentication failed");
auth_chuid(ai, nil);
auth_freeAI(ai);
.P2
.LP
This should be done by the process servicing the client. In some cases,
the process handling the client is the initial process for the server,
if the server is started by
.CW listen .
That is because this program spawns one server process for each client.
In other cases, this has to be done after creating a child process in the server
program just to serve a connection to a client.
.PP
One program that uses
.CW auth_chuid
is
.CW auth/login .
.ix [login]
It can be used to simulate a user login at a terminal. The program prompts
for a user name and a password, and then changes the user identity to that
of the new user, adjusting also the name space and the conventional environment
variables. We use it now to become the user
.CW elf .
.P1
; cat /mnt/factotum/ctl
key proto=p9sk1 dom=dat.escet.urjc.es user=nemo !password?
; auth/login elf
Password: 
% cat /mnt/factotum/ctl
key proto=p9sk1 dom=dat.escet.urjc.es user=elf !password?
% cat /dev/user
elf% 
% cat /dev/hostowner
nemo% 
\fBcontrol-d\fP
;
.P2
.LP
Initially, the factotum used contains just the key for
.CW nemo ,
to authenticate with Plan 9 servers in
.CW dat.escet.urjc.es .
After running
.CW auth/login ,
we obtain a new shell. This one is running with the user id
.CW elf ,
and not
.CW nemo .
As you see, the program started a new factotum for the new shell, which
was given a key for using Plan 9 servers as the user
.CW elf .
.PP
A program might do the same by calling the function
.CW auth_login ,
.ix [auth_login]
which does just this. It uses code like the following one.
.P1
/* authenticate */
ai = auth_userpasswd(user, pass);
if(ai == nil || ai->cap == nil)
	sysfatal("login incorrect");

/* change uid */
auth_chuid(ai, "/lib/namespace");
.P2
.LP
First, it calls the library function
.CW auth_userpasswd
to authenticate a user given its user name and its secret.
Then,
.CW auth_chuid
is used to become the new user.
.BS 2 "Accounts and keys
.LP
.ix account
.ix key
.ix authentication
We are near the end of the discussion about security tools provided by
the operating system, but we did not show how can the authentication
server know which users there are, and which secrets can be used to
authenticate them. Furthermore, we still need to know how the initial
password for a user is established, and how can a user change it.
.PP
Secrets, that is, keys, are not are maintained by the authentication server
process. Instead, another server keeps them. All the keys for users are
handled by a file server, called
.CW keyfs .
.PP
The keys and other information about the user accounts
are actually stored in the file
.CW /adm/keys ,
stored in the file server. To avoid disclosure of the keys, the file is encrypted
using the secret of the host owner in the authentication server machine.
The program
.CW keyfs
.ix [keyfs]
.ix [/adm/keys]
decrypts this file, and serves a file tree at
.CW /mnt/keys
that is the interface for authentication information used by other programs,
including the authentication server
.CW authsrv .
.ix [authsrv]
.ix "authentication server
.PP
For example, the directory
.CW /mnt/keys/nemo
contains information about the account for the user
.CW nemo .
In particular,
.CW /mnt/keys/nemo/key
is the key for such user. That is how the authentication server can
access the secret for
.ix secret
.CW nemo
to know if a remote user is indeed
.CW nemo
or not.
All the operations to create, remove, enable, and disable user
accounts are done through this file system. 
Creating another directory under
.CW /mnt/keys
would create another user entry in
.CW /adm/keys .
And so on.
.PP
In any case, it is not usual to use the file interface directly for
handing user accounts. Instead, commands listed in
.I auth (8)
provide a more convenient interface.
For example, a new user account is created using
.CW auth/changeuser , like in
.P1
; auth/changeuser nemo
.I ...
.P2
.ix [changeuser]
.ix "new account
.ix "new user
.LP
This command is executed in the authentication server. It prompts for
the secret for the new user (which should be only
known to that user, and therefore is typed by him or her), along with
some administrative information. For example, the program asks when
should the account expire, how can the user be reached by email, etc.
.PP
The account created is just a key along with a new user name, that will
be kept encrypted in
.CW /adm/keys .
But this does not allow the new user to use any file servers! Each file server
maintains its own list of users, as you saw. Accounts in the authentication
servers are just for authentication purposes.
.PP
Sometime later, a user might decide to change the secret used for
authentication. This is done with the
.CW passwd
.ix [passwd]
command, which talks directly to the authentication server to change
the secret for the user. This server updates the key using the
.CW /mnt/keys/$user/key
file for the user.
.PP
Because of what we said, you might think that it is necessary for an
administrator to come near each authentication server
to type the password for the host owner. Otherwise, how could
.CW keyfs
decrypt
.CW /adm/keys ?
And the same might apply to file servers and CPU servers. They need
the secret of the host owner to authenticate themselves.
.PP
This is not the case. CPU servers and file servers keep the authentication
domain, the user id of the host owner, and its secret in non-volatile RAM or
.ix NVRAM
.B nvram .
Here,
.I nvram
is just an abstraction, usually implemented using a partition called
.CW nvram
in the hard disk. When a server machine is installed, it is supplied with the
information needed to authenticate. The program
.CW auth/wrkey
.ix [wrkey]
prompts for such information and stores it in the
.CW nvram .
From that point on, the machine can boot unattended. This is very convenient,
specially when considering that CPU servers tend to reboot by themselves when
they loose the connection to the file server.
.PP
There is another place where keys are kept. The
.CW nvram
for the server machines would suffice, because each user knows the
relevant password and can perfectly type it to the
.CW factotum
used when needed. However, users tend to have so many keys these days
that it would be a burden for the user to have to type all of them whenever
they are needed.
.PP
The program
.CW secstore
.ix [secstore]
.ix "secure store"
provides, so called,
.B "single sign on"
to the system. A single sign on facility is one that allows a user to give just
one password (to sign on just once). After that, the user may just access
any of the services he is authorized to use without providing any other secret.
.PP
The
.CW secstore
is a highly secure file server (it uses strong encryption algorithms)
that may store files for each user. The storage used
by the
.CW secstore
is encrypted
.ix [factotum]
using the host owner key. Besides, to prevent the host owner from accessing
the secure files for a user, the files stored are encrypted with the user key
before sending them to the
.CW secstore .
.PP
The most popular use for
.CW secstore
is keeping a file with all the keys for a user, using the format expected by
.CW factotum .
When a user has an account in the
.CW secstore
file server,
.CW factotum
prompts the user for the secret used to access such store. Then, it
retrieves a file named
.CW factotum
from the secure store for the user that is supposed to contain all the user keys.
Because all the keys are now known to
.CW factotum ,
the user is no longer bothered to supply secrets.
.PP
.BS 2 "What now?
.LP
Before concluding, it seemed necessary to note that there are many
other tools for security in Plan 9, like in most other systems. Not to talk
about tools for cryptography, which are the building blocks for security
protocols and therefore, also available in the system.
.PP
For example, it is important in a distributed system to encrypt the connections
between processes running at different machines so that causal users
tapping on the network do not see the data exchanged in clear.
.PP
While using Plan 9, the commands provided by the system try to make
sure that the system remains secure. For example,
.CW passwd
may be run only on a terminal, to change the password. Running it on a
CPU server would mean that the characters might be sent in clear from the
terminal to the CPU server. These days, connections to CPU servers are
usually encrypted, but historically this was an issue and
.CW passwd
refused to run at a CPU server.
.PP
The
.CW AuthInfo
structure contains two fields,
.CW nsecret
and
.CW secret
with a shared secret provided from the authentication server to both the
client and the server. This shared secret could be used to encrypt and
secure the communication channel, before exchanging data between the
client and the server process. We did not show how to do this, but that
is why you have manual pages, which contain examples.
.PP
The
.I tls (3)
.ix TLS
devices provides transparent encryption for network connections.  It was
not discussed here. But it is important to exchange data with servers or clients
requiring TLS to secure their connections.
.PP
Libraries functions, like those described in
.I encrypt (2),
.ix encrypt
provide facilities to encrypt and decrypt data. These ones in particular use
the DES encryption algorithm.
.ix DES
.PP
You have come a long way. It is likely that you have found many different and
new concepts while reading this book. What remains is to practice, and use them.
Hopefully, now that you understand what an operating system is, and how its
abstractions, calls, and commands help you use the machine, you will not
be scared of reading the reference manual that is usually contained along with
each operating system. Good luck.
.ix "good~luck
.SH
Problems
.IP 1
Use Plan 9 to do things you know how to do with other systems.
.IP 2
Optimize answers to the previous question
.ds CH
.bp
 \c
.bp
 \c