[OpenAFS-devel] [LKML] Re: In-kernel Authentication Tokens (PAGs)

Kyle Moffett mrmacman_g4@mac.com
Tue, 13 Jul 2004 21:12:05 -0400


Please CC me, I am not on OpenAFS-devel

On Jul 13, 2004, at 11:37, Tomas Olsson wrote:
> Hi,
> on the openafs-devel list, John Bucy wrote
>> In the current proposal which I believe Kyle Moffett is coding up
>> right now, setuid() and co. don't do anything with the keyrings.
> Is that correct? What's the plan?

The proposal I am working on does not currently need to add additional 
logic
to any existing sys-calls.  It merely associates additional data with 
certain
contexts:
	Thread
	Process
	Process-Group
	Session
	UID
	GID

Each of these objects will have an additional pointer to a key (A 
key-ring is just
a special case of a key that has sub-keys).  When something (EG 
OpenAFS),
requires tokens of a particular type for a particular realm, it 
performs a generic
search using a kernel function.  That search looks through each of the 
above
in order.  If a key is a key-ring, first all keys of the specified type 
are checked,
then all nested key-rings, in arbitrary order.

setuid() et. al. require no additional logic because they just modify 
UID/GID.  If
there are any key-rings associated with the UID/GID, those won't be 
available
any more and the ones of the new UID/GID will, but that is the only 
changing
one part of the set.  On the other hand, keys that are not linked 
through the UID
or GID will remain the same without explicit manipulation.  This makes 
it easy
for me to give a setuid program the ability to read in a file from my 
AFS home.

This has the proviso that SETUID programs should not become insecure if
they discover that they have _less_ privileges than they need, but that 
kind of
program is inherently insecure anyway.

Cheers,
Kyle Moffett

-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCM/CS/IT/U d- s++: a17 C++++>$ UB/L/X/*++++(+)>$ P+++(++++)>$
L++++(+++) E W++(+) N+++(++) o? K? w--- O? M++ V? PS+() PE+(-) Y+
PGP+++ t+(+++) 5 X R? tv-(--) b++++(++) DI+ D+ G e->++++$ h!*()>++$ r  
!y?(-)
------END GEEK CODE BLOCK------


Here is my post on the LKML from about a week ago discussing the 
proposed
system in great detail, in case anyone is interested.

Kyle Moffett wrote:
> 1)	A key-ring is an object independent of what uses it.  It supports 
> operations
> to read, modify, and search it.

When I refer to a key by name here, I am talking about "service@REALM" 
type
name:
> 2)	When a key-ring is searched for a particular key by name and type, 
> first
> it checks all keys of the specified type within said key-ring.  If it 
> does not find it
> there, then it proceeds with all sub-key-rings.
>
> 3)	Keys and key-rings are allocated and referenced through an 
> independent
> number space (Somewhat like the PID allocator)

There are two namespaces here, a global numerical one (referenced 
above),
and a per-process file-descriptor one.  In order to do operations on a 
key or
keyring, you must have a file-descriptor to it.  The only way to 
convert a key
id to a file-descriptor is through the "keyfs" file system (see below) 
which has
whatever permissions are desired.  The permissions model is still very 
much
in flux, if you have any suggestions or questions please contact me.

> 4)	Key and key-ring access should be controlled using permissions and
> POSIX ACLs as though they were files.  In this case, however, the 
> "execute"
> permission bit is used to control in-kernel operations on the keys 
> (EX: AES
> encrypting a block of data using CryptoAPI without being able to read 
> the key.
>
> 5)	Key-rings should be automatically associated with the following 
> things.
> This is also the search order when looking for a key.
> Thread
> Process
> Process Group
> Session
> User
> Group
>
> 6)	User process with the appropriate privileges (Perhaps a new 
> capability
> CAP_LINUX_KEYS or something) can modify/search/link/whatever any/all
> keyrings.  (I'm still not quite sure how much should be allowed.)
>
> 7)	All algorithms working with keys and keyrings should be iterative, 
> not
> recursive, and should be run it process context.
>
> 8)	Graphs of nested key-rings must be non-circular.
>
> 9)	All memory allocated for key-rings and keys should be counted from
> various limits associated with users/processes/etc.
>
> 10)	All kernel key-types should begin with a "+" character, and 
> user-space
> cannot use an unregistered key-type that begins with a "+" character. 
> (This
> means that all keys having a key-type beginning with a "+" character 
> have
> been validated by kernel code.
>
> 11)	A key-ring filesystem should be mounted on /proc/keys:	
> 	types
> 	keys/
> 		<keyID>/
> 			control
> 			type
> 			description
> 			state
>  		<keyringID>/
> 			control
> 			type
> 			description
> 			state
>  			<keyID> => ../<keyID> [symlink]
>
> 12)	It should be impossible to look up keys by number unless said key
> filesystem is mounted.  The "control" entries in the key filesystem 
> can be
> open()ed to get the kind of file handle that KETCTL manipulates.
>
> 13)	A new syscall "keyctl":
>
> KEYCTL_NEW_RING:	Creates a new key-ring and returns its fd
> 	Returns:	int filedesc
> 	Params:
> 		char *desc
> 		int *subkeys
> 		long subkey_count
>
> KEYCTL_NEW_KEY:	Creates a new key and returns its fd
> 	Returns:	int filedesc
> 	Params:
> 		char *type
> 		char *desc
> 		void *data
>
> KEYCTL_SHLOCK
> KEYCTL_EXLOCK
> KEYCTL_UNLOCK:	A mandatory lock on the key/key-ring
> 	Returns:	int error
> 	Params:
> 		int filedesc
> 		int flags
>
> KEYCTL_TYPE:	Retrieves the "type" field
> 	Returns:	long bytes_left
> 	Params:
> 		char *desc
> 		long size
>
> KEYCTL_DESC:	Retrieves the "desc" field
> 	Returns:	long bytes_left
> 	Params:
> 		char *desc
> 		long size
>
> KEYCTL_READ:	Retrieves the "data" field
> 	Returns:	long bytes_left
> 	Params:
> 		char *data
> 		long size
>
> KEYCTL_WRITE:	Modifies the "data" field
> 	Returns:	int error
> 	Params:
> 		char *data
> 		long size
>
> KEYCTL_GET:	Retrieves the current key fd
> 	Returns:	int filedesc
> 	Params:
> 		int type
> 			KEY_THREAD
> 			KEY_PROCESS
> 			KEY_PGROUP
> 			KEY_SESSION
> 			KEY_USER
> 			KEY_GROUP
>
> KEYCTL_SET:	Modifies the current key fd
> 	Returns:	int error
> 	Params:
> 		int type
> 			<See above KEYCTL_GET_KEY>
> 		int filedesc
>
> KEYCTL_ENUM: Enumerates through all keys. NOTE: This must only be
> called with a KEYCTL_SHLOCK, otherwise it might skip keys or repeat
> keys.
> 	Returns:	int error
> 	Params:
> 		int keyring_fd
> 		int *key_fd
>
> KEYCTL_LOOKUP:	Look for a key by type, but don't recurse
> 	Returns:	int filedesc
>
> KEYCTL_SEARCH:	Searches for a specific key by type
> 	Returns:	int filedesc
> 	Params:
> 		char *type
> 		char *desc
>
> KEYCTL_ADD:	Adds a key to a key-ring
> 	Returns:	int error
> 	Params:
> 		int keyring_fd
> 		int key_fd
>
> KEYCTL_REMOVE:	Removes a key from a key-ring
> 	Returns:	int error
> 	Params:
> 		int keyring_fd
> 		int key_fd
>
> KEYCTL_CLEAR:	Removes all keys from a key-ring
> 	Returns:	int error
> 	Params:
> 		int keyring_fd
>
> KEYCTL_REVOKE:	Revokes a specific key file descriptor and any key
> file descriptors it spawned.  This should even apply to keyrings!
> 	Returns:	int error
> 	Params:
> 		int filedesc
>
>
> I think that's just about everything.  Let me know if I got something 
> wrong
> or have another problem with the above.
>
> Cheers,
> Kyle Moffett