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() */
next prev parent 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 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.