public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: Chris Wright <chrisw@osdl.org>
Cc: Blair Strang <bls@asterisk.co.nz>,
	Kyle Moffett <mrmacman_g4@mac.com>,
	Linus Torvalds <torvalds@osdl.org>,
	lkml <linux-kernel@vger.kernel.org>
Subject: Re: In-kernel Authentication Tokens (PAGs)
Date: Wed, 16 Jun 2004 15:37:57 +0100	[thread overview]
Message-ID: <10229.1087396677@redhat.com> (raw)
In-Reply-To: <20040615152912.C22989@build.pdx.osdl.net>

[-- Attachment #1: Type: text/plain, Size: 874 bytes --]


> > I've a sample aklog program (key submission) should you be interested.
> 
> I'd be intereseted.  BTW, I just took a brief look and had a quick
> question.

Please see attached files.

	key_afs.c	Rudimentary kAFS filesystem token handling
	afsutil.h	}
	kernel.c	} aklog program
	aklog.c		}

> > +	if (bprm->e_uid != current->uid)
> > +		suid_keys(current);
> > +	exec_keys(current);
> > +
> 
> would the security module be expected update/revoke keys if the thing changes
> security domains on exec?

I don't know. Currently this patch replaces the old session keyring in favour
of a new empty one upon SUID exec. I suspect that depends on the policy set by
the administrator.

If you've a better suggestion than what I've done, feel free to make it.

> >  	task_lock(current);
> >  	unsafe = unsafe_exec(current);
> >  	security_bprm_apply_creds(bprm, unsafe);

David


[-- Attachment #2: key_afs.c --]
[-- Type: application/octet-stream, Size: 3084 bytes --]

/* key_afs.c: AFS filesystem keys
 *
 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
 * Written 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
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/key.h>
#include <linux/seq_file.h>
#include <asm/errno.h>
#include "cell.h"
#include "internal.h"

static int afs_key_init(struct key *key, const char *desc,
			size_t datalen, const char *data);
static int afs_key_match(const struct key *key, const void *desc);
static void afs_key_clear(struct key *key);
static void afs_key_describe(const struct key *keyring, struct seq_file *m);

struct afs_key_data {
	uint16_t	session_key_size;
	uint16_t	ticket_size;
	int32_t		kvno;
	time_t		expiry;
	uint8_t		data[0];
};

/* AFS Kerberos ticket
 * - the description must be the name of the cell to which applicable
 * - the data is a struct afs_key_data
 */
struct key_type key_type_afs = {
	.name		= "afs",
	.link		= LIST_HEAD_INIT(key_type_afs.link),
	.init		= afs_key_init,
	.match		= afs_key_match,
	.clear		= afs_key_clear,
	.describe	= afs_key_describe,
};

static int afs_key_init(struct key *key, const char *desc,
			size_t datalen, const char *data)
{
	struct afs_key_data *keydata = (void *) data;
	size_t dlen;

	kenter("{%u},%s,%zu,{sk=%hu,tkt=%hu,v=%d,xp=%x}",
	       key->serial, desc, datalen,
	       keydata->session_key_size,
	       keydata->ticket_size,
	       keydata->kvno,
	       (int) keydata->expiry);

	dlen = strlen(desc) + 1;
	key->description.data = kmalloc(dlen, GFP_KERNEL);
	if (!key->description.data) {
		kleave(" = -ENOMEM");
		return -ENOMEM;
	}
	memcpy(key->description.data, desc, dlen);

	key->payload.data = kmalloc(datalen, GFP_KERNEL);
	if (!key->payload.data) {
		kleave(" = -ENOMEM");
		return -ENOMEM;
	}

	key->datalen = datalen;
	memcpy(key->payload.data, data, datalen);

	kleave(" = 0");
	return 0;
}

static int afs_key_match(const struct key *key, const void *desc)
{
	if (!key->description.data)
		return 0;

	return strcmp(key->description.data, desc) == 0 ? 1 : 0;
}

static void afs_key_clear(struct key *key)
{
	if (key->description.data)
		kfree(key->description.data);
	if (key->payload.data)
		kfree(key->payload.data);
}

static void afs_key_describe(const struct key *key, struct seq_file *m)
{
	struct afs_key_data *keydata;

	if (!key->description.data) {
		seq_puts(m, "[anon]");
		return;
	}

	keydata = key->payload.data;

	seq_printf(m, "%s => { s=%hu t=%hu v=%d x=%lx }",
		   (char *) key->description.data,
		   keydata->session_key_size,
		   keydata->ticket_size,
		   keydata->kvno,
		   (int) keydata->expiry - CURRENT_TIME.tv_sec);
}

int __init afs_key_register(void)
{
	return register_key_type(&key_type_afs);
}

void __exit afs_key_unregister(void)
{
	unregister_key_type(&key_type_afs);
}

[-- Attachment #3: afsutil.h --]
[-- Type: application/octet-stream, Size: 762 bytes --]

/* afsutil.h: AFS client utility library
 *
 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
 * Written 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
 * 2 of the License, or (at your option) any later version.
 */

#ifndef _AFS_UTIL_H
#define _AFS_UTIL_H

#include <stdlib.h>
#include <stdint.h>

extern int afsutil_authorise_krb5(const char *cell,
				  const char *realm,
				  time_t expiry,
				  size_t session_key_size,
				  const void *session_key,
				  int ticket_kvno,
				  size_t ticket_size,
				  const void *ticket);
				  

#endif /* _AFS_UTIL_H */

[-- Attachment #4: kernel.c --]
[-- Type: application/octet-stream, Size: 2527 bytes --]

/* kernel.c: routines for talking to the kernel
 *
 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
 * Written 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
 * 2 of the License, or (at your option) any later version.
 */

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <alloca.h>
#include <sys/prctl.h>

/* Manage a process's keyrings */
#define PR_SPEC_THREAD_KEYRING		0	/* - specifier for thread-specific keyring */
#define PR_SPEC_PROCESS_KEYRING		1	/* - specifier for process-specific keyring */
#define PR_SPEC_SESSION_KEYRING		2	/* - specifier for session-specific keyring */
#define PR_SPEC_USER_KEYRING		3	/* - specifier for UID-specific keyring */
#define PR_SPEC_GROUP_KEYRING		4	/* - specifier for GID-specific keyring */

#define PR_GET_KEYRING_ID		15	/* ask for specified keyring's ID */
#define PR_CLEAR_KEYRING		16	/* clear contents of specified keyring */
#define PR_NEW_SESSION_KEYRING		17	/* start a new session keyring */
#define PR_ADD_NEW_KEY			18	/* add a key to specified keyring */

typedef int32_t key_serial_t;

struct afs_key_data {
	uint16_t	session_key_size;
	uint16_t	ticket_size;
	int32_t		kvno;
	time_t		expiry;
	uint8_t		data[0];
};

/*****************************************************************************/
/*
 * pass authorisation information to the kernel indicating that we have a valid
 * kerberos4 ticket
 */
int afsutil_authorise_krb5(const char *cell,
			   const char *realm,
			   time_t expiry,
			   size_t session_key_size,
			   const void *session_key,
			   int ticket_kvno,
			   size_t ticket_size,
			   const void *ticket)
{
	struct afs_key_data *keydata;
	uint16_t payload_size;
	void *buffer;
	int ret;

	payload_size =
		sizeof(struct afs_key_data) +
		session_key_size +
		ticket_size;

	buffer = alloca(sizeof(uint16_t) + payload_size);

	*(uint16_t *) buffer = payload_size;

	keydata = buffer + sizeof(uint16_t);
	keydata->session_key_size	= session_key_size;
	keydata->ticket_size		= ticket_size;
	keydata->kvno			= ticket_kvno;
	keydata->expiry			= expiry;

	memcpy(keydata->data, session_key, session_key_size);
	memcpy(keydata->data + session_key_size, ticket, ticket_size);

	if (prctl(PR_ADD_NEW_KEY, PR_SPEC_SESSION_KEYRING,
		  "afs", cell, buffer) < 0)
		return -1;

	return 0;
} /* end afsutil_authorise_krb5() */

[-- Attachment #5: aklog.c --]
[-- Type: application/octet-stream, Size: 5621 bytes --]

/* aklog.c: request a Kerberos ticket grant for an AFS cell
 *
 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
 * Written 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
 * 2 of the License, or (at your option) any later version.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <krb5.h>
#include <com_err.h>
#include <kerberosIV/krb.h>
#include <afsutil.h>

extern int krb524_convert_creds_kdc(krb5_context, krb5_creds *, CREDENTIALS *);

char *realm = "CAMBRIDGE.REDHAT.COM"; //NULL;
char *cell = "cambridge.redhat.com"; //NULL;
int debug = 0;

krb5_principal	princ;
krb5_context	krb5context;
krb5_ccache	tktcache;

static void format(void) __attribute__((noreturn));
static void format(void)
{
	fprintf(stderr,
		"aklog [-d] [-c] [<cell>] [-k <realm>]\n");

	exit(2);
}

#define KRBERR(X,M) do { if ((X) != KSUCCESS) krberr((X),(M)); } while(0)

void krberr(errcode_t kerr, const char *where) __attribute__((noreturn));
void krberr(errcode_t kerr, const char *where)
{
	fprintf(stderr, "%s: %s\n", where, error_message(kerr));
	exit(1);
}

/*****************************************************************************/
/*
 * parse the argument list
 */
void parse_args(char **argv)
{
	if (!*argv)
		return;

	if (strcmp(argv[0], "-help") == 0)
		format();

	if (strcmp(argv[0], "-d") == 0) {
		debug++;
		argv++;
	}

	if (strcmp(argv[0], "-c") == 0)
		argv++;

	if (!*argv)
		format();

	if (argv[0][0] == '-')
		format();
	cell = *argv;
	argv++;

	if (!*argv)
		return;

	if (strcmp(argv[0], "-k") != 0)
		format();
	argv++;

	if (!*argv)
		return;

	if (argv[0][0] == '-')
		format();
	realm = *argv;
	argv++;

	if (*argv)
		format();

} /* end parse_args() */

/*****************************************************************************/
/*
 * try to obtain a kerberos ticket
 */
int obtain_ticket(krb5_creds **creds, const char *service, const char *cell)
{
	krb5_error_code kerr;
	krb5_creds request;

	/* set up a description of what we actually want */
	memset(&request, 0, sizeof(request));

	kerr = krb5_build_principal(krb5context, &request.server,
				    strlen(realm), realm,
				    service, cell,
				    NULL);
	KRBERR(kerr, "failed to construct request");

	request.client			= princ;
	request.times.endtime		= 0;
	request.keyblock.enctype	= ENCTYPE_DES_CBC_CRC;

	/* go and prod the Kerberos servers */
	kerr = krb5_get_credentials(krb5context, 0, tktcache, &request, creds);
	if (kerr != KSUCCESS && kerr != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN)
		KRBERR(kerr, "error talking to KDC");

	return kerr == KSUCCESS;
} /* end obtain_ticket() */

/*****************************************************************************/
/*
 *
 */
int main(int argc, char *argv[])
{
	krb5_error_code kerr;
	unsigned char *cp;
	krb5_creds *creds5;
	CREDENTIALS creds4;
	time_t time;
	char buf1[100];
	int loop;

	parse_args(argv + 1);

	kerr = krb5_init_context(&krb5context);
	KRBERR(kerr, "failed to initialise the Kerberos5 context");

	/* may need to find the default realm */
	if (!realm) {
		kerr = krb5_get_default_realm(krb5context, &realm);
		KRBERR(kerr, "failed to get the default realm");
	}

	/* may need to find the default AFS cell */
	if (!cell) {
	}

	/* open the appropriate Kerberos ticket cache */
	kerr = krb5_cc_default(krb5context, &tktcache);
	KRBERR(kerr, "unable to resolve default cred cache");

	kerr = krb5_cc_get_principal(krb5context, tktcache, &princ);
	KRBERR(kerr, "unable to extract the principal from the cache");

	/* ask the KDC to give us an AFS ticket */
	if (!cell || !obtain_ticket(&creds5, "afs", cell)) {
		if (!obtain_ticket(&creds5, "afs", NULL)) {
			fprintf(stderr, "couldn't obtain AFS ticket\n");
			exit(2);
		}
	}

	kerr = krb5_cc_close(krb5context, tktcache);
	KRBERR(kerr, "error closing cache");

	/* ask the KDC to turn the Kerberos 5 ticket into a Kerberos 4
	 * ticket */
	kerr = krb524_convert_creds_kdc(krb5context, creds5, &creds4);
	KRBERR(kerr, "unable to convert to a kerberos V4 ticket");

	/* dump the credential data obtained */
	if (debug) {
		printf("SERVICE  : %s%s%s@%s\n",
		       creds4.service,
		       creds4.instance[0] ? "/" : "",
		       creds4.instance,
		       creds4.realm);
		printf("PRINCIPAL: %s%s%s@%s\n",
		       creds4.pname,
		       creds4.pinst[0] ? "/" : "", creds4.pinst,
		       creds4.realm);

		time = creds4.issue_date;
		printf("ISSUED   : %s", ctime_r(&time, buf1));

		time = creds5->times.endtime;
		printf("EXPIRES  : %s", ctime_r(&time, buf1));

		printf("SESSION  : key=[");
		cp = (unsigned char *) &creds4.session;
		for (loop = 0; loop < sizeof(creds4.session); loop++)
			printf("%02x", *cp++);
		printf("]\n");

		printf("TICKET   : version %d, length %d:",
		       creds4.kvno, creds4.ticket_st.length);

		cp = (unsigned char *) &creds4.ticket_st.dat;
		for (loop = 0; loop < creds4.ticket_st.length; loop++) {
			if (loop % (76 / 2) == 0)
				printf("\n    ");
			printf("%02x", *cp++);
		}
		printf("\n");
	}

	/* pass the ticket to the AFS filesystem */
	if (afsutil_authorise_krb5(cell,
				   realm,
				   creds5->times.endtime,
				   sizeof(creds4.session),
				   &creds4.session,
				   creds4.kvno,
				   creds4.ticket_st.length,
				   creds4.ticket_st.dat) < 0
	    ) {
		fprintf(stderr, "unable to pass token to kernel: %m\n");
		exit(1);
	}

	krb5_free_creds(krb5context, creds5);

	krb5_free_context(krb5context);

	return 0;
} /* end main() */

  reply	other threads:[~2004-06-16 14:40 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-12  2:37 In-kernel Authentication Tokens (PAGs) Kyle Moffett
2004-06-12  3:13 ` Andy Lutomirski
2004-06-12  4:57   ` Kyle Moffett
2004-06-12  5:34     ` Andy Lutomirski
2004-06-12 12:51       ` Kyle Moffett
2004-06-12 15:37         ` Andy Lutomirski
2004-06-12 17:15           ` Kyle Moffett
2004-06-12  3:15 ` Chris Wright
2004-06-12  4:48   ` Kyle Moffett
2004-06-12 20:53     ` Chris Wright
2004-06-12 21:15       ` Kyle Moffett
2004-06-12 21:44         ` Chris Wright
2004-06-12 21:58           ` Kyle Moffett
2004-06-12 22:51             ` Chris Wright
2004-06-12 23:40               ` Kyle Moffett
2004-06-12 22:51 ` Trond Myklebust
2004-06-12 23:33   ` Kyle Moffett
2004-06-12 23:58     ` Trond Myklebust
2004-06-13  0:23       ` Kyle Moffett
2004-06-15  6:38         ` Blair Strang
2004-06-15  7:03           ` Trond Myklebust
2004-06-15  9:36             ` David Howells
2004-06-15 19:00               ` Kyle Moffett
2004-06-15 22:07                 ` Chris Wright
2004-06-15 23:48                   ` Kyle Moffett
2004-06-16  0:01                     ` Chris Wright
2004-06-16  0:06                       ` Kyle Moffett
2004-06-16 14:22                 ` David Howells
2004-06-15 22:29               ` Chris Wright
2004-06-16 14:37                 ` David Howells [this message]
2004-06-15 23:59               ` Kyle Moffett
2004-06-16 14:49                 ` David Howells
2004-06-17  1:13                   ` Kyle Moffett
2004-06-17 11:48                     ` David Howells
2004-06-17 19:06                       ` Kyle Moffett
2004-06-23 12:29                         ` David Howells
2004-06-23 21:03                           ` Kyle Moffett
2004-06-29 17:07                           ` Kyle Moffett
2004-07-07 18:54                             ` John Bucy
2004-07-08  1:29                               ` Kyle Moffett

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=10229.1087396677@redhat.com \
    --to=dhowells@redhat.com \
    --cc=bls@asterisk.co.nz \
    --cc=chrisw@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mrmacman_g4@mac.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox