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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox