All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: torvalds@osdl.org, akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org, linux-afs@lists.infradead.org,
	linux-fsdevel@vger.kernel.org,
	David Howells <dhowells@redhat.com>
Subject: [PATCH 15/17] AFS: Implement the PSetTokens pioctl
Date: Tue, 16 Jun 2009 21:40:02 +0100	[thread overview]
Message-ID: <20090616204002.4526.22111.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <20090616203845.4526.60013.stgit@warthog.procyon.org.uk>

Implement the PSetTokens pioctl for AFS.  This will submit a security token for
caching.

This can be tested with the OpenAFS userspace tools using the klog program,
which should add a key to the session keyring with something like:

	[root@andromeda ~]# echo password | klog -pipe admin
	[root@andromeda ~]# keyctl show
	Session Keyring
	       -3 --alswrv      0     0  keyring: _ses
	147139749 --alswrv      0    -1   \_ keyring: _uid.0
	457362442 --als--v      0     0   \_ rxrpc: cambridge.redhat.com

Note that 'klog -setpag' is not supported by this patch as there's currently
no way for a process to replace its parent process's session keyring.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 fs/afs/cell.c           |   15 ++++
 fs/afs/internal.h       |    1 
 fs/afs/pioctl.c         |  177 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/afscall.h |   14 ++++
 include/linux/venus.h   |    1 
 5 files changed, 208 insertions(+), 0 deletions(-)


diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index e19c13f..b900fc7 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -227,6 +227,21 @@ int afs_cell_init(char *rootcell)
 }
 
 /*
+ * get a reference to the root cell
+ */
+struct afs_cell *afs_get_root_cell(void)
+{
+	struct afs_cell *cell;
+
+	read_lock(&afs_cells_lock);
+	cell = afs_cell_root;
+	afs_get_cell(cell);
+	read_unlock(&afs_cells_lock);
+
+	return cell;
+}
+
+/*
  * lookup a cell record
  */
 struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz)
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 9a8e8a2..cf08782 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -467,6 +467,7 @@ extern struct list_head afs_proc_cells;
 
 #define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
 extern int afs_cell_init(char *);
+extern struct afs_cell *afs_get_root_cell(void);
 extern struct afs_cell *afs_cell_create(const char *, char *);
 extern struct afs_cell *afs_cell_lookup(const char *, unsigned);
 extern struct afs_cell *afs_grab_cell(struct afs_cell *);
diff --git a/fs/afs/pioctl.c b/fs/afs/pioctl.c
index ffbec0c..e6ea69f 100644
--- a/fs/afs/pioctl.c
+++ b/fs/afs/pioctl.c
@@ -2,6 +2,8 @@
  *
  * Copyright (C) 2008 Jacob Thebault-Spieker <summatusmentis@gmail.com>
  *
+ * Modified by David Howells <dhowells@redhat.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
@@ -12,6 +14,10 @@
 #include <linux/pioctl.h>
 #include <linux/venus.h>
 #include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/key.h>
+#include <linux/keyctl.h>
+#include <keys/rxrpc-type.h>
 #include "internal.h"
 
 /*
@@ -219,6 +225,173 @@ long afs_pioctl(struct dentry *dentry, int cmd, struct vice_ioctl *arg)
 }
 
 /*
+ * Set a user's rxkad authentication tokens
+ */
+static long afs_PSetTokens(struct vice_ioctl *arg)
+{
+	struct rxrpc_key_data_v2 *payload;
+	struct clear_token details;
+	struct afs_cell *cell;
+	const char *cp;
+	key_ref_t keyring_r, key_r;
+	size_t in_size, loop;
+	void *in, *in_next, *ticket;
+	char *cellname, *keyname, *dp;
+	long ret;
+	u32 tktlen, tmp, flag;
+
+	_enter("");
+
+	/* decode the argument block */
+	in_next = arg->in;
+	in_size = arg->in_size;
+
+#define CHECK(n)				\
+	do {					\
+		if (in_size < (n))		\
+			goto underflow;		\
+		in = in_next;			\
+		in_size -= (n);			\
+		in_next += (n);			\
+	} while(0)
+
+#define DECODE(to)				\
+	do {					\
+		CHECK(sizeof(*(to)));		\
+		memcpy(to, in, sizeof(*(to)));	\
+	} while(0)
+
+	DECODE(&tktlen);
+	_debug("tktlen: %u", tktlen);
+	if (tktlen > INT_MAX)
+		goto invalid;
+	CHECK(tktlen);
+	ticket = in;
+	DECODE(&tmp);
+	_debug("clear token %u", tmp);
+	if (tmp != sizeof(struct clear_token))
+		goto invalid;
+	DECODE(&details);
+	_debug("ah:%x vi:%x bts:%x ets:%x (e-b:%u) (CT:%lx)",
+	       details.auth_handle, details.vice_id,
+	       details.begin_timestamp, details.end_timestamp,
+	       details.end_timestamp - details.begin_timestamp,
+	       CURRENT_TIME.tv_sec);
+	if (details.vice_id == UINT_MAX)
+		goto invalid;
+	if (details.auth_handle == UINT_MAX)
+		details.auth_handle = 999;
+
+	/* flags and cellname are optional, defaulting to the root cell */
+	_debug("in_size: %zu", in_size);
+	if (in_size != 0) {
+		DECODE(&flag);
+		_debug("flag: %x", flag);
+
+		if (flag & 0x8000) {
+			/* the caller wants us to give our parent a new PAG
+			 * - we don't support this currently
+			 */
+			_leave(" = -EACCES");
+			return -EACCES;
+		}
+
+		/* remainder is cell name */
+		CHECK(sizeof(char));
+		cellname = in;
+		for (loop = 0; loop < in_size; loop++)
+			if (!isprint(cellname[loop]))
+				goto invalid;
+
+		if (cellname[loop] != '\0')
+			goto invalid;
+		cell = NULL;
+
+		_debug("cellname: %s", cellname);
+	} else {
+		cell = afs_get_root_cell();
+		cellname = cell->name;
+		flag = 1;
+	}
+
+#undef DECODE
+#undef CHECK
+
+	/* construct the key name */
+	ret = -ENOMEM;
+	keyname = kmalloc(4 + strlen(cellname) + 1, GFP_KERNEL);
+	if (!keyname)
+		goto error_nokeyname;
+
+	memcpy(keyname, "afs@", 4);
+	dp = keyname + 4;
+	cp = cellname;
+	while (*cp)
+		*dp++ = toupper(*cp++);
+	*dp = 0;
+
+	/* we install the authentication token as a key */
+	payload = kmalloc(sizeof(*payload) + tktlen, GFP_KERNEL);
+	if (!payload)
+		goto error_nopayload;
+
+	payload->kif_version	= 2;
+	payload->security_index	= RXRPC_SECURITY_RXKAD;
+	payload->ticket_length	= tktlen;
+	payload->vice_id	= details.vice_id;
+	payload->start		= details.begin_timestamp;
+	payload->expiry		= details.end_timestamp;
+	payload->kvno		= details.auth_handle;
+	memcpy(payload->session_key, details.session_key, 8);
+	memcpy(payload->ticket, ticket, tktlen);
+
+	/* add the key to the session keyring */
+	keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 1, 0,
+				    WANT_KEY_WRITE);
+	if (IS_ERR(keyring_r)) {
+		_debug("keyring lookup failed");
+		ret = PTR_ERR(keyring_r);
+		goto error;
+	}
+
+	/* create or update the requested key and add it to the target
+	 * keyring */
+	key_r = key_create_or_update(keyring_r, "rxrpc", keyname,
+				     payload, sizeof(*payload) + tktlen,
+				     KEY_PERM_UNDEF, KEY_ALLOC_IN_QUOTA);
+	key_ref_put(keyring_r);
+
+	if (IS_ERR(key_r)) {
+		_debug("key create failed");
+		ret = PTR_ERR(key_r);
+		goto error;
+	}
+
+	_debug("key serial: %x", key_ref_to_ptr(key_r)->serial);
+
+	key_ref_put(key_r);
+	arg->out_size = 0;
+	ret = 0;
+
+error:
+	kfree(payload);
+error_nopayload:
+	kfree(keyname);
+error_nokeyname:
+	afs_put_cell(cell);
+	_leave(" = %ld", ret);
+	return ret;
+
+underflow:
+	_leave(" = -EINVAL [short arg]");
+	return -EINVAL;
+
+invalid:
+	_leave(" = -EINVAL [invalid arg]");
+	return -EINVAL;
+}
+
+/*
  * The AFS pathless pioctl handler
  */
 long afs_pathless_pioctl(int cmd, struct vice_ioctl *arg)
@@ -231,6 +404,10 @@ long afs_pathless_pioctl(int cmd, struct vice_ioctl *arg)
 #define VIOC_COMMAND(nr) (_VICEIOCTL(nr) & ~IOCSIZE_MASK)
 
 	switch (cmd & ~IOCSIZE_MASK) {
+	case VIOC_COMMAND(PSetTokens):
+		ret = afs_PSetTokens(arg);
+		break;
+
 	default:
 		printk(KERN_DEBUG "AFS: Unsupported pioctl command %x\n", cmd);
 		ret = -EOPNOTSUPP;
diff --git a/include/linux/afscall.h b/include/linux/afscall.h
index 00054f0..7635aab 100644
--- a/include/linux/afscall.h
+++ b/include/linux/afscall.h
@@ -2,6 +2,8 @@
  *
  * Copyright (C) 2008 Jacob Thebault-Spieker <summatusmentis@gmail.com>
  *
+ * Modified by David Howells <dhowells@redhat.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
@@ -14,6 +16,7 @@
 #define AFSCALL_PIOCTL 0x14
 
 /* pioctl commands */
+#define PSetTokens	3		/* get authentication tokens for user */
 #define PGetVolStat	4		/* get volume status */
 #define PWhereIs	14		/* find out where a volume is located */
 #define PGetFID		22		/* get file ID */
@@ -40,4 +43,15 @@ struct VolumeStatus {
 	int	PartMaxBlocks;	/* size of volume's partition */
 };
 
+/*
+ * User details when getting or submitting a token
+ */
+struct clear_token {
+	u32	auth_handle;		/* key version number */
+	u8	session_key[8];		/* session encryption key */
+	u32	vice_id;		/* client/user ID */
+	u32	begin_timestamp;	/* time_t at which ticket starts */
+	u32	end_timestamp;		/* time_t at which ticket expires */
+};
+
 #endif /* _LINUX_AFSCALL_H */
diff --git a/include/linux/venus.h b/include/linux/venus.h
index ea8e468..b90e5f2 100644
--- a/include/linux/venus.h
+++ b/include/linux/venus.h
@@ -17,6 +17,7 @@
 /*
  * pioctl commands (not usable as ioctls)
  */
+#define VIOCSETTOK		_VICEIOCTL(PSetTokens)
 #define VIOCGETVOLSTAT		_VICEIOCTL(PGetVolStat)
 #define VIOCWHEREIS		_VICEIOCTL(PWhereIs)
 #define VIOCGETFID		_VICEIOCTL(PGetFID)


  parent reply	other threads:[~2009-06-16 20:42 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-16 20:38 [PATCH 00/17] [RFC] AFS: Implement OpenAFS pioctls(version)s David Howells
2009-06-16 20:38 ` [PATCH 01/17] VFS: Implement the pioctl() system call David Howells
2009-06-16 20:54   ` Christoph Hellwig
2009-06-17  0:19   ` David Howells
2009-06-17  9:02     ` Alan Cox
2009-06-16 20:38 ` [PATCH 02/17] VFS: Implement the AFS " David Howells
2009-06-16 20:39 ` [PATCH 03/17] VFS: Implement handling for pathless pioctls David Howells
2009-06-17  7:47   ` Andreas Dilger
2009-06-17 18:26   ` David Howells
2009-06-16 20:39 ` [PATCH 04/17] AFS: Add key request for pioctl David Howells
2009-06-16 20:39 ` [PATCH 05/17] AFS: Handle pathless pioctls aimed at AFS David Howells
2009-06-16 20:39 ` [PATCH 06/17] VFS: Define pioctl command wrappers David Howells
2009-06-16 20:39 ` [PATCH 07/17] AFS: Implement the PGetFid pioctl David Howells
2009-06-16 20:39 ` [PATCH 08/17] AFS: Implement the PGetFileCell pioctl David Howells
2009-06-16 20:39 ` [PATCH 09/17] AFS: Implement the PGetVolStat pioctl David Howells
2009-06-16 20:39 ` [PATCH 10/17] AFS: Implement the PWhereIs pioctl David Howells
2009-06-17  7:51   ` Andreas Dilger
2009-06-17 18:05   ` David Howells
2009-06-16 20:39 ` [PATCH 11/17] AFS: Implement the PFlushCB pioctl David Howells
2009-06-16 20:39 ` [PATCH 12/17] KEYS: Export lookup_user_key() and the key permission request flags David Howells
2009-06-16 20:39 ` [PATCH 13/17] RxRPC: Record extra data in key David Howells
2009-06-16 20:39 ` [PATCH 14/17] RxRPC: Declare the security index constants symbolically David Howells
2009-06-16 20:40 ` David Howells [this message]
2009-06-16 20:40 ` [PATCH 16/17] KEYS: Add a function by which the contents of a keyring can be enumerated David Howells
2009-06-16 20:40 ` [PATCH 17/17] AFS: Implement the PGetTokens pioctl David Howells
2009-06-16 22:59 ` [PATCH 00/17] [RFC] AFS: Implement OpenAFS pioctls(version)s David Howells
2009-06-16 23:11   ` Alan Cox
2009-06-17  0:25   ` David Howells
2009-06-17  7:55     ` Andreas Dilger
2009-06-17 16:09       ` Linus Torvalds
2009-06-17 18:37         ` Al Viro
2009-06-17 18:44           ` Linus Torvalds
2009-06-17 18:52             ` Al Viro
2009-06-17 19:28             ` David Howells
2009-06-18 12:50               ` Olivier Galibert
2009-06-17 17:24       ` David Howells
2009-06-17 17:33         ` Linus Torvalds
2009-06-17 18:03         ` David Howells
2009-06-17 18:24           ` Linus Torvalds
2009-06-17 18:30           ` Theodore Tso
2009-06-17 19:14             ` david
2009-06-17 19:30             ` David Howells
2009-06-17 19:51           ` David Howells
2009-06-17 20:09             ` Linus Torvalds
2009-06-17  9:00     ` Alan Cox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090616204002.4526.22111.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-afs@lists.infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.