Control of Access to General Objects
Protecting memory is a
specific case of the more general problem of protecting objects. As
multiprogramming has developed, the numbers and kinds of objects shared have
also increased. Here are some examples of the kinds of objects for which
protection is desirable:
·
memory
·
a file or data set on an auxiliary storage device
·
an executing program in memory
·
a directory of files
·
a hardware device
·
a data structure, such as a stack
·
a table of the operating system
·
instructions, especially privileged instructions
·
passwords and the user authentication mechanism
·
the protection mechanism itself
The memory protection
mechanism can be fairly simple because every memory access is guaranteed to go
through certain points in the hardware. With more general objects, the number
of points of access may be larger, a central authority through which all
accesses pass may be lacking, and the kind of access may not simply be limited
to read, write, or execute.
Furthermore, all accesses to
memory occur through a program, so we can refer to the program or the
programmer as the accessing agent. In this book, we use terms like the user or
the subject in describing an access to a general object. This user or subject
could be a person who uses a computing system, a programmer, a program, another
object, or something else that seeks to use an object.
There are several
complementary goals in protecting objects.
·
Check every access. We may want to revoke a user's privilege to
access an object. If we have previously authorized the user to access the
object, we do not necessarily intend that the user should retain indefinite
access to the object. In fact, in some situations, we may want to prevent
further access immediately after we revoke authorization. For this reason,
every access by a user to an object should be checked.
·
Enforce least privilege. The principle of least privilege states
that a subject should have access to the smallest number of objects necessary
to perform some task. Even if extra information would be useless or harmless if
the subject were to have access, the subject should not have that additional
access. For example, a program should not have access to the absolute memory
address to which a page number reference translates, even though the program
could not use that address in any effective way. Not allowing access to
unnecessary objects guards against security weaknesses if a part of the
protection mechanism should fail.
·
Verify acceptable usage. Ability to access is a yes-or-no decision.
But it is equally important to check that the activity to be performed on an
object is appropriate. For example, a data structure such as a stack has
certain acceptable operations, including push, pop, clear, and so on. We may
want not only to control who or what has access to a stack but also to be
assured that the accesses performed are legitimate stack accesses.
In the next section we
consider protection mechanisms appropriate for general objects of unspecified
types, such as the kinds of objects listed above. To make the explanations
easier to understand, we sometimes use an example of a specific object, such as
a file. Note, however, that a general mechanism can be used to protect any of
the types of objects listed.
Directory
One simple way to protect an
object is to use a mechanism that works like a file directory. Imagine we are
trying to protect files (the set of objects) from users of a computing system
(the set of subjects). Every file has a unique owner who possesses
"control" access rights (including the rights to declare who has what
access) and to revoke access to any person at any time. Each user has a file
directory, which lists all the files to which that user has access.
Clearly, no user can be allowed to write in the
file directory because that would be a way to forge access to a file.
Therefore, the operating system must maintain all file directories, under
commands from the owners of files. The obvious rights to files are the common
read, write, and execute familiar on many shared systems. Furthermore, another
right, owner, is possessed by the owner, permitting that user to grant and
revoke access rights. Figure 4-10 shows
an example of a file directory.
This approach is easy to
implement because it uses one list per user, naming all the objects that user
is allowed to access. However, several difficulties can arise. First, the list
becomes too large if many shared objects, such as libraries of subprograms or a
common table of users, are accessible to all users. The directory of each user
must have one entry for each such shared object, even if the user has no
intention of accessing the object. Deletion must be reflected in all
directories. (See Sidebar 4-2 for a
different issue concerning deletion of objects.)
A second difficulty is revocation of access. If owner A has passed to user B the right to
read file F, an entry for F is made in the directory for B. This granting of
access implies a level of trust between A and B. If A later questions that
trust, A may want to revoke the access right of B. The operating system can
respond easily to the single request to delete the right of B to access F
because that action involves deleting one entry from a specific directory. But
if A wants to remove the rights of everyone to access F, the operating system
must search each individual directory for the entry F, an activity that can be
time consuming on a large system. For example, large timesharing systems or
networks of smaller systems can easily have 5,000 to 10,000 active accounts.
Moreover, B may have passed the access right for F to another user, so A may
not know that F's access exists and should be revoked. This problem is
particularly serious in a network.
Sidebar
4-2: "Out, Damned Spot! Out, I Say!"
Shakespeare's Lady Macbeth symbolically
and obsessively sought to remove from her hands the blood of the man her
husband had murdered at her instigation. As others have found (less
dramatically), removing bits can be real, critical, and challenging.
Early
Microsoft operating systems didn't actually erase a deleted file; they simply
flagged its directory entry to show the file had been deleted. A user who
accidentally deleted a file could recover the file by resetting the flag in the
directory. Now Microsoft implements a recycle bin (originally an idea from
Apple).
What happens to the bits of deleted
files? In early multiuser operating systems, it was possible to retrieve
someone else's data by looking through the trash. The technique was to create a
large file, and then before writing to the file, read from it to get the
contents previously written in that memory or storage space. Although an
attacker had to restructure the data (blocks might not be stored contiguously,
and a large space might include scraps of data from several other users),
sensitive data could be found with some luck and some work. This flaw led to an
operating system's enforcing "object reuse." The operating system had
to ensure that no residue from a previous user was accessible by another. The
operating system could erase (for example, overwrite with all 0s) all storage
being assigned to a new user, or it could enforce a policy that a user could
read from a space only after having written into it.
Magnetic
devices retain some memory of what was written in an area. As President Nixon's
secretary discovered with her 17-minute gap, with specialized equipment
engineers can sometimes bring back something previously written and then
written over. This property, called "magnetic remanence," causes
organizations with sensitive data to require a seven- or more pass erasure,
rewriting first with 0s, then with 1s, and then with a random pattern of 0s and
1s. And agencies with the most sensitive data opt to destroy the medium rather
than risk inadvertent disclosure. Garfinkel and Shelat discuss sanitizing
magnetic media in [GAR03a].
A third difficulty involves
pseudonyms. Owners A and B may have two different files named F, and they may
both want to allow access by S. Clearly, the directory for S cannot contain two
entries under the same name for different files. Therefore, S has to be able to
uniquely identify the F for A (or B). One approach is to include the original
owner's designation as if it were part of the file name, with a notation such
as A:F (or B:F).
Suppose, however, that S has trouble
remembering file contents from the name F. Another approach is to allow S to
name F with any name unique to the directory of S. Then, F from A could be
called Q to S. As shown in Figure 4-11,
S may have forgotten that Q is F from A, and so S requests access again from A
for F. But by now A may have more trust in S, so A transfers F with greater
rights than before. This action opens up the possibility that one subject, S,
may have two distinct sets of access rights to F, one under the name Q and one
under the name F. In this way, allowing pseudonyms leads to multiple
permissions that are not necessarily consistent. Thus, the directory approach
is probably too simple for most object protection situations.
Access Control List
An alternative representation is the access control list. There is one such list for each object, and the list shows all subjects who should have access to the object and
what their access is. This approach differs from the directory list because
there is one access control list per object; a directory is created for each
subject. Although this difference seems small, there are some significant
advantages.
To see how, consider subjects A and S, both of
whom have access to object F. The operating system will maintain just one
access list for F, showing the access rights for A and S, as shown in Figure 4-12. The access control list can include
general default entries for any users. In this way, specific users can have
explicit rights, and all other users can have a default set of rights. With
this organization, a public file or program can be shared by all possible users
of the system without the need for an entry for the object in the individual
directory of each user.
The Multics operating system
used a form of access control list in which each user belonged to three
protection classes: a user, a group, and a compartment. The user designation
identified a specific subject, and the group designation brought together
subjects who had a common interest, such as coworkers on a project. The
compartment confined an untrusted object; a program executing in one
compartment could not access objects in another compartment without specific
permission. The compartment was also a way to collect objects that were
related, such as all files for a single project.
To see how this type of
protection might work, suppose every user who initiates access to the system
identifies a group and a compartment with which to work. If Adams logs in as
user Adams in group Decl and compartment Art2, only objects having
Adams-Decl-Art2 in the access control list are accessible in the session.
By itself, this kind of
mechanism would be too restrictive to be usable. Adams cannot create general
files to be used in any session. Worse yet, shared objects would have not only
to list Adams as a legitimate subject but also to list Adams under all
acceptable groups and all acceptable compartments for each group.
The solution is the use of wild cards, meaning placeholders that designate "any
user" (or "any group" or "any compartment"). An access
control list might specify access by Adams-Decl-Art1, giving specific rights to
Adams if working in group Decl on compartment Art1. The list might also specify
Adams-*-Art1, meaning that Adams can access the object from any group in
compartment Art1. Likewise, a notation of *-Decl-* would mean "any user in
group Decl in any compartment." Different placements of the wildcard
notation * have the obvious interpretations.
The access control list can
be maintained in sorted order, with * sorted as coming after all specific
names. For example, Adams-Decl-* would come after all specific compartment
designations for Adams. The search for access permission continues just until
the first match. In the protocol, all explicit designations are checked before
wild cards in any position, so a specific access right would take precedence
over a wildcard right. The last entry on an access list could be *-* -*,
specifying rights allowable to any user not explicitly on the access list. By
using this wildcard device, a shared public object can have a very short access
list, explicitly naming the few subjects that should have access rights
different from the default.
Access Control Matrix
We can think of the directory
as a listing of objects accessible by a single subject, and the access list as
a table identifying subjects that can access a single object. The data in these
two representations are equivalent, the distinction being the ease of use in
given situations.
As an alternative, we can use an access control matrix, a table in which
each row represents a subject, each column represents an object, and each entry
is the set of access rights for that subject to that object. An example
representation of an access control matrix is shown in Table 4-1. In general,
the access control matrix is sparse (meaning that most cells are empty): Most
subjects do not have access rights to most objects. The access matrix can be represented as a
list of triples, having the form <subject, object, rights>. Searching a
large number of these triples is inefficient enough that this implementation is
seldom used.
Capability
So far, we have examined
protection schemes in which the operating system must keep track of all the
protection objects and rights. But other approaches put some of the burden on
the user. For example, a user may be required to have a ticket or pass that
enables access, much like a ticket or identification card that cannot be
duplicated. More formally, we say that a capability
is an unforgeable token that gives the possessor certain rights to an object. The
Multics [SAL74], CAL [LAM76], and Hydra [WUL74]
systems used capabilities for access control. In theory, a subject can create
new objects and can specify the operations allowed on those objects. For
example, users can create objects, such as files, data segments, or
subprocesses, and can also specify the acceptable kinds of operations, such as
read, write, and execute. But a user can also create completely new objects,
such as new data structures, and can define types of accesses previously
unknown to the system.
A capability is a ticket
giving permission to a subject to have a certain type of access to an object.
For the capability to offer solid protection, the ticket must be unforgeable.
One way to make it unforgeable is to not give the ticket directly to the user.
Instead, the operating system holds all tickets on behalf of the users. The
operating system returns to the user a pointer to an operating system data
structure, which also links to the user. A capability can be created only by a
specific request from a user to the operating system. Each capability also
identifies the allowable accesses.
Alternatively, capabilities
can be encrypted under a key available only to the access control mechanism. If
the encrypted capability contains the identity of its rightful owner, user A
cannot copy the capability and give it to user B.
One possible access right to an object is
transfer or propagate. A subject having this right can pass copies of
capabilities to other subjects. In turn, each of these capabilities also has a
list of permitted types of accesses, one of which might also be transfer. In
this instance, process A can pass a copy of a capability to B, who can then
pass a copy to C. B can prevent further distribution of the capability (and
therefore prevent further dissemination of the access right) by omitting the
transfer right from the rights passed in the capability to C. B might still
pass certain access rights to C, but not the right to propagate access rights
to other subjects.
As a process executes, it operates in a domain or local name space. The domain is the collection of objects to which
the process has access. A domain for a user at a given time might include some
programs, files, data segments, and I/O devices such as a printer and a terminal.
An example of a domain is shown in Figure 4-13.
As execution continues, the
process may call a subprocedure, passing some of the objects to which it has
access as arguments to the subprocedure. The domain of the subprocedure is not
necessarily the same as that of its calling procedure; in fact, a calling
procedure may pass only some of its objects to the subprocedure, and the
subprocedure may have access rights to other objects not accessible to the
calling procedure. The caller may also pass only some of its access rights for
the objects it passes to the subprocedure. For example, a procedure might pass
to a subprocedure the right to read but not modify a particular data value.
Because each capability identifies a single
object in a domain, the collection of capabilities defines the domain. When a
process calls a subprocedure and passes certain objects to the subprocedure,
the operating system forms a stack of all the capabilities of the current
procedure. The operating system then creates new capabilities for the
subprocedure, as shown in Figure 4-14.
Operationally, capabilities
are a straightforward way to keep track of the access rights of subjects to
objects during execution. The capabilities are backed up by a more
comprehensive table, such as an access control matrix or an access control
list. Each time a process seeks to use a new object, the operating system
examines the master list of objects and subjects to determine whether the
object is accessible. If so, the operating system creates a capability for that
object.
Capabilities must be stored
in memory inaccessible to normal users. One way of accomplishing this is to
store capabilities in segments not pointed at by the user's segment table or to
enclose them in protected memory as from a pair of base/bounds registers.
Another approach is to use a tagged architecture machine to identify
capabilities as structures requiring protection.
During execution, only the
capabilities of objects that have been accessed by the current process are kept
readily available. This restriction improves the speed with which access to an
object can be checked. This approach is essentially the one used in Multics, as
described in [FAB74].
Capabilities can be revoked.
When an issuing subject revokes a capability, no further access under the
revoked capability should be permitted. A capability table can contain pointers
to the active capabilities spawned under it so that the operating system can
trace what access rights should be deleted if a capability is revoked. A
similar problem is deleting capabilities for users who are no longer active.
Kerberos
Fundamental research on
capabilities laid the groundwork for subsequent production use in systems such
as Kerberos [STE88] (studied in greater
detail in Chapter 7). Kerberos
implements both authentication and access authorization by means of
capabilities, called tickets, secured with symmetric cryptography. Microsoft
has based much of its access control in NT+ on Kerberos.
Kerberos requires two
systems, called the authentication
server (AS) and the ticket- granting
server (TGS), which are both part of the key distribution center (KDC). A user presents an authenticating
credential (such as a password) to the authentication server and receives a ticket showing that the user has
passed authentication. Obviously, the ticket must be encrypted to prevent the
user from modifying or forging one claiming to be a different user, and the
ticket must contain some provision to prevent one user from acquiring another
user's ticket to impersonate that user.
Now let us suppose that a
user, Joe, wants to access a resource R (for example, a file, printer, or
network port). Joe sends the TGS his authenticated ticket and a request to use
R. Assuming Joe is allowed access, the TGS returns to Joe two tickets: One
shows Joe that his access to R has been authorized, and the second is for Joe
to present to R in order to access R.
Kerberos implements single
sign-on; that is, a user signs on once and from that point on all the user's
(allowable) actions are authorized without the user needing to sign on again.
So if a user wants access to a resource in a different domain, say on a
different system or in a different environment or even a different company or
institution, as long as authorization rights have been established between the
two domains, the user's access takes place without the user's signing on to a
different system.
Kerberos accomplishes its
local and remote authentication and authorization with a system of shared
secret encryption keys. In fact, each user's password is used as an encryption
key. (That trick also means that passwords are never exposed, reducing the risk
from interception.) We study the exact mechanism of Kerberos in Chapter 7.
Procedure-Oriented Access Control
One goal of access control is restricting not
just which subjects have access to an object, but also what they can do to that
object. Read versus write access can be controlled rather readily by most
operating systems, but more complex control is not so easy to achieve.
By procedure-oriented protection, we imply the existence of a
procedure that controls access to objects (for example, by performing its own
user authentication to strengthen the basic protection provided by the basic
operating system). In essence, the procedure forms a capsule around the object,
permitting only certain specified accesses.
Procedures can ensure that
accesses to an object be made through a trusted interface. For example, neither
users nor general operating system routines might be allowed direct access to
the table of valid users. Instead, the only accesses allowed might be through
three procedures: one to add a user, one to delete a user, and one to check
whether a particular name corresponds to a valid user. These procedures,
especially add and delete, could use their own checks to make sure that calls
to them are legitimate.
Procedure-oriented protection
implements the principle of information hiding because the means of
implementing an object are known only to the object's control procedure. Of
course, this degree of protection carries a penalty of inefficiency. With
procedure-oriented protection, there can be no simple, fast access, even if the
object is frequently used.
Our survey of access control
mechanisms has intentionally progressed from simple to complex. Historically,
as the mechanisms have provided greater flexibility, they have done so with a
price of increased overhead. For example, implementing capabilities that must
be checked on each access is far more difficult than implementing a simple
directory structure that is checked only on a subject's first access to an
object. This complexity is apparent both to the user and to the implementer.
The user is aware of additional protection features, but the naïve user may be
frustrated or intimidated at having to select protection options with little
understanding of their usefulness. The implementation complexity becomes
apparent in slow response to users. The balance between simplicity and
functionality is a continuing battle in security.
Role-Based Access Control
We have not yet distinguished among kinds of
users, but we want some users (such as administrators) to have significant
privileges, and we want others (such as regular users or guests) to have lower
privileges. In companies and educational institutions, this can get complicated
when an ordinary user becomes an administrator or a baker moves to the
candlestick makers' group. Role-based
access control lets us associate privileges with groups, such as all
administrators can do this or candlestick makers are forbidden to do this.
Administering security is easier if we can control access by job demands, not
by person. Access control keeps up with a person who changes responsibilities,
and the system administrator does not have to choose the appropriate access
control settings for someone. For more details on the nuances of role-based
access control, see [FER03].
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.