Linux authentication / credential management

David Howells (dhowells@redhat.com)
Wed, 09 Apr 2003 16:12:14 +0100


Hi Linus,

Would you be willing to consider having a "credential cache" in Linux 2.5 (or
is this something you'd rather leave to 2.7)?

The first part of what I'm thinking of is a structure like the following that
has a Process Authentication Group ID and a list of authentication tokens for
filesystems such as AFS & NFSv4 kerberos keys, NTFS ACLs, SAMBA login details.

struct auth_session {
struct atomic_t usage;
pag_t pag; /* process auth group ID */
struct list_head tokens;
rwlock_t lock;
};

Each token would be defined as follows, the most significant bit being a
pointer to a blob of arbitrary data for the use of the filesystem:

struct auth_token {
struct list_head link;
struct auth_token_ops *ops;
atomic_t usage;
time_t expiry;
void *data;
};

struct auth_token_ops {
const char *type;
void (*release)(struct auth_session *session,
struct auth_token *token);
};

Two additional system calls would be required: setpag() to create a new
session and attach to it, and getpag() to find out what a process's session ID
is.

Note that these sessions are different from job-control sessions and process
groups.

The second part is to detach all the user and group information from the task
structure and put it into a separate structure of its own, which each task (or
task group) would then refer to:

struct auth_context {
atomic_t usage;
uid_t uid, euid, suid;
gid_t gid, egid, sgid;
int ngroups;
gid_t groups[NGROUPS];
struct user_struct *user;
struct auth_session *session;
};

struct task_struct {
...
struct auth_context *auth;
struct auth_context *fsauth;
...
};

Furthermore each struct file would refer to one of these contexts, the pointer
being set at the moment of opening:

struct file {
...
struct auth_context *f_auth;
...
};

struct file *dentry_open(...)
{
...
f->f_auth = get_auth_context(current->fsauth);
...
}

This structure would then become "copy on modify if shared", otherwise files
could have their security details changed when the process that opened them
changes its details.

Alternatively, the task structure could just point to the credential cache
entry for that process.

ADDITIONAL POSSIBILITIES
========================

(*) It may be worth making the supplementary group list a token dangling from
the auth_session struct.

Alternatively, the groups could be put in a separate ref-counted
structure of their own.

(*) Make auth_context into a stack of permission structures, pushing extra
nodes on to effect separation of EUID, UID and SUID for example. The
structure would then become:

struct auth_context {
struct auth_context *next;
atomic_t usage;
int type; /* 0=real, 1=temp effective */
uid_t uid;
gid_t gid;
int ngroups;
gid_t groups[NGROUPS];
struct user_struct *user;
struct auth_session *session;
};

The effective credentials would just be whatever is at the TOS.

Temporary changes of authentication tokens would be fairly simple (just
push and pop). SetUID programs would just push another context on the
stack, which then could be popped off by setuid(SAVED_IDS).

Things like setresuid() would manipulate the top three entries on the
stack.

(*) The kernel capabilities masks could also be offloaded into this
structure.

(*) A set of convenience functions could be provided to:

- extract the current UID/GID from a context (eg: used by creat)
- test RWX permission against a context (eg: used by open)

This would then abstract the UID/GID concept, making it easier to extend
the access control system.

(*) It might be possible to pass an auth_context* to readpage instead of a
file*.

David
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/