From 461eeb37f19bc04c35028df8f242c426f2663087 Mon Sep 17 00:00:00 2001 From: ericm Date: Thu, 16 Nov 2006 04:33:12 +0000 Subject: [PATCH] branch: b_new_cmd port from b1_8_gss: gss daemons sync to nfs-utils-1.0.10-CITI-3 --- lustre/utils/gss/Makefile.am | 1 + lustre/utils/gss/README | 2 +- lustre/utils/gss/context.h | 10 +- lustre/utils/gss/context_heimdal.c | 6 +- lustre/utils/gss/context_lucid.c | 592 ++++ lustre/utils/gss/context_mit.c | 571 +--- lustre/utils/gss/gssd.c | 23 +- lustre/utils/gss/gssd.h | 3 +- lustre/utils/gss/gssd_main_loop.c | 6 +- lustre/utils/gss/gssd_proc.c | 39 +- lustre/utils/gss/krb5_util.c | 29 +- lustre/utils/gss/nfs-utils-1.0.10-lustre.diff | 4126 +++++++++++++------------ lustre/utils/gss/svcgssd_mech2file.c | 6 +- 13 files changed, 2838 insertions(+), 2576 deletions(-) create mode 100644 lustre/utils/gss/context_lucid.c diff --git a/lustre/utils/gss/Makefile.am b/lustre/utils/gss/Makefile.am index 34ccfaa..01ee650 100644 --- a/lustre/utils/gss/Makefile.am +++ b/lustre/utils/gss/Makefile.am @@ -12,6 +12,7 @@ sbin_PROGRAMS = lgssd lsvcgssd l_idmap COMMON_SRCS = \ context.c \ + context_lucid.c \ context_mit.c \ context_heimdal.c \ context_spkm3.c \ diff --git a/lustre/utils/gss/README b/lustre/utils/gss/README index 77a6662..94d1dda 100644 --- a/lustre/utils/gss/README +++ b/lustre/utils/gss/README @@ -4,7 +4,7 @@ All files came from standard nfs-utils package, applied with patches created by Cluster File Systems Inc. 1. Stock nfs-utils-1.0.10.tgz -2. Apply nfs-utils-1.0.10-CITI_NFS4_ALL-1.dif from Center for Information +2. Apply nfs-utils-1.0.10-CITI_NFS4_ALL-3.dif from Center for Information Technology Integration, University of Michigan (http://www.citi.umich.edu/projects/nfsv4/linux/) 3. Apply lustre patch: nfs-utils-1.0.10-lustre.diff diff --git a/lustre/utils/gss/context.h b/lustre/utils/gss/context.h index 71638b8..8243f5d 100644 --- a/lustre/utils/gss/context.h +++ b/lustre/utils/gss/context.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2004 The Regents of the University of Michigan. + Copyright (c) 2004-2006 The Regents of the University of Michigan. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,6 +31,14 @@ #ifndef _CONTEXT_H_ #define _CONTEXT_H_ +/* Hopefully big enough to hold any serialized context */ +#define MAX_CTX_LEN 4096 + +/* New context format flag values */ +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 +#define KRB5_CTX_FLAG_CFX 0x00000002 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 + int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf, gss_OID mech); int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf); diff --git a/lustre/utils/gss/context_heimdal.c b/lustre/utils/gss/context_heimdal.c index edd4dfc..5520cbc 100644 --- a/lustre/utils/gss/context_heimdal.c +++ b/lustre/utils/gss/context_heimdal.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2004 The Regents of the University of Michigan. + Copyright (c) 2004-2006 The Regents of the University of Michigan. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ #include "config.h" +#ifndef HAVE_LUCID_CONTEXT_SUPPORT #ifdef HAVE_HEIMDAL #include @@ -46,8 +47,6 @@ #include "gss_oids.h" #include "write_bytes.h" -#define MAX_CTX_LEN 4096 - int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key) { gss_buffer_desc tmp; @@ -265,3 +264,4 @@ out_err: } #endif /* HAVE_HEIMDAL */ +#endif /* HAVE_LUCID_CONTEXT_SUPPORT */ diff --git a/lustre/utils/gss/context_lucid.c b/lustre/utils/gss/context_lucid.c new file mode 100644 index 0000000..bfae6a6 --- /dev/null +++ b/lustre/utils/gss/context_lucid.c @@ -0,0 +1,592 @@ +/* + * COPYRIGHT (c) 2006 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "config.h" + +#ifdef HAVE_LUCID_CONTEXT_SUPPORT + +/* + * Newer versions of MIT and Heimdal have lucid context support. + * We can use common code if it is supported. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifndef OM_uint64 +typedef uint64_t OM_uint64; +#endif +#include + +#include "gss_util.h" +#include "gss_oids.h" +#include "err_util.h" +#include "context.h" + +static int +write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) +{ + gss_buffer_desc tmp; + + if (WRITE_BYTES(p, end, key->type)) return -1; + tmp.length = key->length; + tmp.value = key->data; + if (write_buffer(p, end, &tmp)) return -1; + return 0; +} + +static int +prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, + gss_buffer_desc *buf) +{ + char *p, *end; + static int constant_zero = 0; + unsigned char fakeseed[16]; + uint32_t word_send_seq; + gss_krb5_lucid_key_t enc_key; + int i; + char *skd, *dkd; + gss_buffer_desc fakeoid; + + /* + * The new Kerberos interface to get the gss context + * does not include the seed or seed_init fields + * because we never really use them. But for now, + * send down a fake buffer so we can use the same + * interface to the kernel. + */ + memset(&enc_key, 0, sizeof(enc_key)); + memset(&fakeoid, 0, sizeof(fakeoid)); + + if (!(buf->value = calloc(1, MAX_CTX_LEN))) + goto out_err; + p = buf->value; + end = buf->value + MAX_CTX_LEN; + + if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err; + + /* seed_init and seed not used by kernel anyway */ + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; + if (write_bytes(&p, end, &fakeseed, 16)) goto out_err; + + if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.sign_alg)) goto out_err; + if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.seal_alg)) goto out_err; + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; + word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */ + if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err; + if (write_oid(&p, end, &krb5oid)) goto out_err; + +#ifdef HAVE_HEIMDAL + /* + * The kernel gss code expects des-cbc-raw for all flavors of des. + * The keytype from MIT has this type, but Heimdal does not. + * Force the Heimdal keytype to 4 (des-cbc-raw). + * Note that the rfc1964 version only supports DES enctypes. + */ + if (lctx->rfc1964_kd.ctx_key.type != 4) { + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n", + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4); + lctx->rfc1964_kd.ctx_key.type = 4; + } +#endif + printerr(2, "%s: serializing keys with enctype %d and length %d\n", + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, + lctx->rfc1964_kd.ctx_key.length); + + /* derive the encryption key and copy it into buffer */ + enc_key.type = lctx->rfc1964_kd.ctx_key.type; + enc_key.length = lctx->rfc1964_kd.ctx_key.length; + if ((enc_key.data = calloc(1, enc_key.length)) == NULL) + goto out_err; + skd = (char *) lctx->rfc1964_kd.ctx_key.data; + dkd = (char *) enc_key.data; + for (i = 0; i < enc_key.length; i++) + dkd[i] = skd[i] ^ 0xf0; + if (write_lucid_keyblock(&p, end, &enc_key)) { + free(enc_key.data); + goto out_err; + } + free(enc_key.data); + + if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key)) + goto out_err; + + buf->length = p - (char *)buf->value; + return 0; +out_err: + printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); + if (buf->value) free(buf->value); + buf->length = 0; + if (enc_key.data) free(enc_key.data); + return -1; +} + +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ + +/* for 3DES */ +#define KG_USAGE_SEAL 22 +#define KG_USAGE_SIGN 23 +#define KG_USAGE_SEQ 24 + +/* for rfc???? */ +#define KG_USAGE_ACCEPTOR_SEAL 22 +#define KG_USAGE_ACCEPTOR_SIGN 23 +#define KG_USAGE_INITIATOR_SEAL 24 +#define KG_USAGE_INITIATOR_SIGN 25 + +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */ +enum seal_alg { + SEAL_ALG_NONE = 0xffff, + SEAL_ALG_DES = 0x0000, + SEAL_ALG_1 = 0x0001, /* not published */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ + SEAL_ALG_DES3KD = 0x0002 +}; + +#define KEY_USAGE_SEED_ENCRYPTION 0xAA +#define KEY_USAGE_SEED_INTEGRITY 0x55 +#define KEY_USAGE_SEED_CHECKSUM 0x99 +#define K5CLENGTH 5 + +/* Flags for version 2 context flags */ +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 +#define KRB5_CTX_FLAG_CFX 0x00000002 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 + +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* + * We don't have "legal" access to these MIT-only + * structures located in libk5crypto + */ +extern void krb5int_enc_arcfour; +extern void krb5int_enc_des3; +extern void krb5int_enc_aes128; +extern void krb5int_enc_aes256; +extern int krb5_derive_key(); + +static void +key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout) +{ + memset(kout, '\0', sizeof(kout)); +#ifdef HAVE_KRB5 + kout->enctype = lin->type; + kout->length = lin->length; + kout->contents = lin->data; +#else + kout->keytype = lin->type; + kout->keyvalue.length = lin->length; + kout->keyvalue.data = lin->data; +#endif +} + +static void +key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout) +{ + memset(lout, '\0', sizeof(lout)); +#ifdef HAVE_KRB5 + lout->type = kin->enctype; + lout->length = kin->length; + lout->data = kin->contents; +#else + lout->type = kin->keytype; + lout->length = kin->keyvalue.length; + memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length); +#endif +} + +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* XXX Hack alert! XXX Do NOT submit upstream! XXX */ +/* + * Function to derive a new key from a given key and given constant data. + */ +static krb5_error_code +derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out, + int usage, char extra) +{ + krb5_error_code code; + unsigned char constant_data[K5CLENGTH]; + krb5_data datain; + int keylength; + void *enc; + krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */ +#ifdef HAVE_HEIMDAL + krb5_context kcontext; + krb5_keyblock *outkey; +#endif + + /* + * XXX Hack alert. We don't have "legal" access to these + * values and structures located in libk5crypto + */ + switch (in->type) { + case ENCTYPE_DES3_CBC_SHA1: +#ifdef HAVE_KRB5 + case ENCTYPE_DES3_CBC_RAW: +#endif + keylength = 24; +#ifdef HAVE_KRB5 + enc = &krb5int_enc_des3; +#endif + break; + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: + keylength = 16; +#ifdef HAVE_KRB5 + enc = &krb5int_enc_aes128; +#endif + break; + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: + keylength = 32; +#ifdef HAVE_KRB5 + enc = &krb5int_enc_aes256; +#endif + break; + default: + code = KRB5_BAD_ENCTYPE; + goto out; + } + + /* allocate memory for output key */ + if ((out->data = malloc(keylength)) == NULL) { + code = ENOMEM; + goto out; + } + out->length = keylength; + out->type = in->type; + + /* Convert to correct format for call to krb5_derive_key */ + key_lucid_to_krb5(in, &kin); + key_lucid_to_krb5(out, &kout); + + datain.data = (char *) constant_data; + datain.length = K5CLENGTH; + + ((char *)(datain.data))[0] = (usage>>24)&0xff; + ((char *)(datain.data))[1] = (usage>>16)&0xff; + ((char *)(datain.data))[2] = (usage>>8)&0xff; + ((char *)(datain.data))[3] = usage&0xff; + + ((char *)(datain.data))[4] = (char) extra; + +#ifdef HAVE_KRB5 + code = krb5_derive_key(enc, &kin, &kout, &datain); +#else + if ((code = krb5_init_context(&kcontext))) { + } + code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey); +#endif + if (code) { + free(out->data); + out->data = NULL; + goto out; + } +#ifdef HAVE_KRB5 + key_krb5_to_lucid(&kout, out); +#else + key_krb5_to_lucid(outkey, out); + krb5_free_keyblock(kcontext, outkey); + krb5_free_context(kcontext); +#endif + + out: + if (code) + printerr(0, "ERROR: %s: returning error %d (%s)\n", + __FUNCTION__, code, error_message(code)); + return (code); +} + + +/* + * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx), + * to send to the kernel for newer encryption types -- or for DES3. + * + * The new format is: + * + * u32 initiate; ( whether we are the initiator or not ) + * s32 endtime; + * u32 flags; + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 + * #define KRB5_CTX_FLAG_CFX 0x00000002 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 + * u64 seq_send; + * u32 enctype; ( encrption type of keys ) + * u32 size_of_each_key; ( size of each key in bytes ) + * u32 number_of_keys; ( N -- should always be 3 for now ) + * keydata-1; ( Ke ) + * keydata-2; ( Ki ) + * keydata-3; ( Kc ) + * + */ +static int +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx, + gss_buffer_desc *buf) +{ + char *p, *end; + uint32_t v2_flags = 0; + gss_krb5_lucid_key_t enc_key; + gss_krb5_lucid_key_t derived_key; + gss_buffer_desc fakeoid; + uint32_t enctype; + uint32_t keysize; + uint32_t numkeys; + + memset(&enc_key, 0, sizeof(enc_key)); + memset(&fakeoid, 0, sizeof(fakeoid)); + + if (!(buf->value = calloc(1, MAX_CTX_LEN))) + goto out_err; + p = buf->value; + end = buf->value + MAX_CTX_LEN; + + /* Version 2 */ + if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err; + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; + + if (lctx->initiate) + v2_flags |= KRB5_CTX_FLAG_INITIATOR; + if (lctx->protocol != 0) + v2_flags |= KRB5_CTX_FLAG_CFX; + if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1) + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; + + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; + + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; + + /* Protocol 0 here implies DES3 or RC4 */ + printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol); + if (lctx->protocol == 0) { + enctype = lctx->rfc1964_kd.ctx_key.type; +#ifdef HAVE_HEIMDAL + /* + * The kernel gss code expects ENCTYPE_DES3_CBC_RAW (6) for + * 3des keys, but Heimdal key has ENCTYPE_DES3_CBC_SHA1 (16). + * Force the Heimdal enctype to 6. + */ + if (enctype == ENCTYPE_DES3_CBC_SHA1) { + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n", + __FUNCTION__, enctype, 6); + + enctype = 6; + } +#endif + keysize = lctx->rfc1964_kd.ctx_key.length; + numkeys = 3; /* XXX is always gonna be three? */ + } else { + if (lctx->cfx_kd.have_acceptor_subkey) { + enctype = lctx->cfx_kd.acceptor_subkey.type; + keysize = lctx->cfx_kd.acceptor_subkey.length; + } else { + enctype = lctx->cfx_kd.ctx_key.type; + keysize = lctx->cfx_kd.ctx_key.length; + } + numkeys = 3; + } + printerr(2, "%s: serializing %d keys with enctype %d and size %d\n", + __FUNCTION__, numkeys, enctype, keysize); + if (WRITE_BYTES(&p, end, enctype)) goto out_err; + if (WRITE_BYTES(&p, end, keysize)) goto out_err; + if (WRITE_BYTES(&p, end, numkeys)) goto out_err; + + if (lctx->protocol == 0) { + /* derive and send down: Ke, Ki, and Kc */ + /* Ke */ + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, + lctx->rfc1964_kd.ctx_key.length)) + goto out_err; + + /* Ki */ + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, + lctx->rfc1964_kd.ctx_key.length)) + goto out_err; + + /* Kc */ + if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, + &derived_key, + KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) + goto out_err; + if (write_bytes(&p, end, derived_key.data, + derived_key.length)) + goto out_err; + free(derived_key.data); + } else { + gss_krb5_lucid_key_t *keyptr; + uint32_t sign_usage, seal_usage; + + if (lctx->cfx_kd.have_acceptor_subkey) + keyptr = &lctx->cfx_kd.acceptor_subkey; + else + keyptr = &lctx->cfx_kd.ctx_key; + +#if 0 + if (lctx->initiate == 1) { + sign_usage = KG_USAGE_INITIATOR_SIGN; + seal_usage = KG_USAGE_INITIATOR_SEAL; + } else { + sign_usage = KG_USAGE_ACCEPTOR_SIGN; + seal_usage = KG_USAGE_ACCEPTOR_SEAL; + } +#else + /* FIXME + * These are from rfc4142, but I don't understand: if we supply + * different 'usage' value for client & server, then the peers + * will have different derived keys. How could this work? + * + * Here we simply use old SIGN/SEAL values until we find the + * answer. --ericm + * FIXME + */ + sign_usage = KG_USAGE_SIGN; + seal_usage = KG_USAGE_SEAL; +#endif + + /* derive and send down: Ke, Ki, and Kc */ + + /* Ke */ + if (derive_key_lucid(keyptr, &derived_key, + seal_usage, KEY_USAGE_SEED_ENCRYPTION)) + goto out_err; + if (write_bytes(&p, end, derived_key.data, + derived_key.length)) + goto out_err; + free(derived_key.data); + + /* Ki */ + if (derive_key_lucid(keyptr, &derived_key, + seal_usage, KEY_USAGE_SEED_INTEGRITY)) + goto out_err; + if (write_bytes(&p, end, derived_key.data, + derived_key.length)) + goto out_err; + free(derived_key.data); + + /* Kc */ + if (derive_key_lucid(keyptr, &derived_key, + sign_usage, KEY_USAGE_SEED_CHECKSUM)) + goto out_err; + if (write_bytes(&p, end, derived_key.data, + derived_key.length)) + goto out_err; + free(derived_key.data); + } + + buf->length = p - (char *)buf->value; + return 0; + +out_err: + printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n", + __FUNCTION__); + if (buf->value) { + free(buf->value); + buf->value = NULL; + } + buf->length = 0; + if (enc_key.data) { + free(enc_key.data); + enc_key.data = NULL; + } + return -1; +} +int +serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) +{ + OM_uint32 maj_stat, min_stat; + void *return_ctx = 0; + OM_uint32 vers; + gss_krb5_lucid_context_v1_t *lctx = 0; + int retcode = 0; + + printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__); + maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx, + 1, &return_ctx); + if (maj_stat != GSS_S_COMPLETE) { + pgsserr("gss_export_lucid_sec_context", + maj_stat, min_stat, &krb5oid); + goto out_err; + } + + /* Check the version returned, we only support v1 right now */ + vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version; + switch (vers) { + case 1: + lctx = (gss_krb5_lucid_context_v1_t *) return_ctx; + break; + default: + printerr(0, "ERROR: unsupported lucid sec context version %d\n", + vers); + goto out_err; + break; + } + + /* + * Now lctx points to a lucid context that we can send down to kernel + * + * Note: we send down different information to the kernel depending + * on the protocol version and the enctyption type. + * For protocol version 0 with all enctypes besides DES3, we use + * the original format. For protocol version != 0 or DES3, we + * send down the new style information. + */ + + if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4) + retcode = prepare_krb5_rfc1964_buffer(lctx, buf); + else + retcode = prepare_krb5_rfc4121_buffer(lctx, buf); + + maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); + if (maj_stat != GSS_S_COMPLETE) { + pgsserr("gss_export_lucid_sec_context", + maj_stat, min_stat, &krb5oid); + printerr(0, "WARN: failed to free lucid sec context\n"); + } + + if (retcode) { + printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n", + __FUNCTION__, retcode); + goto out_err; + } + + return 0; + +out_err: + printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); + return -1; +} + + + +#endif /* HAVE_LUCID_CONTEXT_SUPPORT */ diff --git a/lustre/utils/gss/context_mit.c b/lustre/utils/gss/context_mit.c index 164ca92..cd6ab0f 100644 --- a/lustre/utils/gss/context_mit.c +++ b/lustre/utils/gss/context_mit.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2004 The Regents of the University of Michigan. + Copyright (c) 2004-2006 The Regents of the University of Michigan. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,77 +29,29 @@ */ #include "config.h" + +#ifndef HAVE_LUCID_CONTEXT_SUPPORT +#ifdef HAVE_KRB5 + #include #include #include #include #include +#include +#include #include "gss_util.h" #include "gss_oids.h" #include "err_util.h" #include "context.h" -#ifdef HAVE_KRB5 #include -/* for 3DES */ -#define KG_USAGE_SEAL 22 -#define KG_USAGE_SIGN 23 -#define KG_USAGE_SEQ 24 - -/* for rfc???? */ -#define KG_USAGE_ACCEPTOR_SEAL 22 -#define KG_USAGE_ACCEPTOR_SIGN 23 -#define KG_USAGE_INITIATOR_SEAL 24 -#define KG_USAGE_INITIATOR_SIGN 25 - -/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */ -enum seal_alg { - SEAL_ALG_NONE = 0xffff, - SEAL_ALG_DES = 0x0000, - SEAL_ALG_1 = 0x0001, /* not published */ - SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ - SEAL_ALG_DES3KD = 0x0002 -}; - -#define KEY_USAGE_SEED_ENCRYPTION 0xAA -#define KEY_USAGE_SEED_INTEGRITY 0x55 -#define KEY_USAGE_SEED_CHECKSUM 0x99 -#define K5CLENGTH 5 - -/* Flags for version 2 context flags */ -#define KRB5_CTX_FLAG_INITIATOR 0x00000001 -#define KRB5_CTX_FLAG_CFX 0x00000002 -#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 - -/* - * XXX Hack alert. We don't have "legal" access to these - * structures located in libk5crypto - */ -extern void krb5int_enc_arcfour; -extern void krb5int_enc_des3; -extern void krb5int_enc_aes128; -extern void krb5int_enc_aes256; -extern int krb5_derive_key(); - -void *get_enc_provider(); - -/* XXX spkm3 seems to actually want it this big, yipes. */ -#define MAX_CTX_LEN 4096 - - - -#ifdef HAVE_LUCID_CONTEXT_SUPPORT - -/* Don't use the private structure, use the exported lucid structure */ -#include - -#elif (KRB5_VERSION > 131) +#if (KRB5_VERSION > 131) /* XXX argggg, there's gotta be a better way than just duplicating this * whole struct. Unfortunately, this is in a "private" header file, * so this is our best choice at this point :-/ - * - * XXX Does this match the Heimdal definition? */ + */ typedef struct _krb5_gss_ctx_id_rec { unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */ @@ -174,451 +126,71 @@ typedef struct _krb5_gss_ctx_id_rec { #endif /* KRB5_VERSION */ -#ifdef HAVE_LUCID_CONTEXT_SUPPORT /* Lucid context support */ static int -write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) +write_keyblock(char **p, char *end, struct _krb5_keyblock *arg) { gss_buffer_desc tmp; - if (WRITE_BYTES(p, end, key->type)) return -1; - tmp.length = key->length; - tmp.value = key->data; + if (WRITE_BYTES(p, end, arg->enctype)) return -1; + tmp.length = arg->length; + tmp.value = arg->contents; if (write_buffer(p, end, &tmp)) return -1; return 0; } -static void -key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout) -{ - memset(kout, '\0', sizeof(kout)); - kout->enctype = lin->type; - kout->length = lin->length; - kout->contents = lin->data; -} - -static void -key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout) -{ - memset(lout, '\0', sizeof(lout)); - lout->type = kin->enctype; - lout->length = kin->length; - lout->data = kin->contents; -} - /* - * Function to derive a new key from a given key and given constant data. + * XXX Hack alert! XXX Do NOT submit upstream! + * XXX Hack alert! XXX Do NOT submit upstream! + * + * We shouldn't be using these definitions + * + * XXX Hack alert! XXX Do NOT submit upstream! + * XXX Hack alert! XXX Do NOT submit upstream! */ -static krb5_error_code -derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out, - int usage, char extra) -{ - krb5_error_code code; - unsigned char constant_data[K5CLENGTH]; - krb5_data datain; - int keylength; - void *enc; - krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */ - - /* - * XXX Hack alert. We don't have "legal" access to these - * values and structures located in libk5crypto - */ - switch (in->type) { - case ENCTYPE_DES3_CBC_RAW: - keylength = 24; - enc = &krb5int_enc_des3; - break; - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - keylength = 16; - enc = &krb5int_enc_aes128; - break; - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - keylength = 32; - enc = &krb5int_enc_aes256; - break; - default: - code = KRB5_BAD_ENCTYPE; - goto out; - } - - /* allocate memory for output key */ - if ((out->data = malloc(keylength)) == NULL) { - code = ENOMEM; - goto out; - } - out->length = keylength; - out->type = in->type; - - /* Convert to correct format for call to krb5_derive_key */ - key_lucid_to_krb5(in, &kin); - key_lucid_to_krb5(out, &kout); - - datain.data = (char *) constant_data; - datain.length = K5CLENGTH; - - datain.data[0] = (usage>>24)&0xff; - datain.data[1] = (usage>>16)&0xff; - datain.data[2] = (usage>>8)&0xff; - datain.data[3] = usage&0xff; - - datain.data[4] = (char) extra; - - if ((code = krb5_derive_key(enc, &kin, &kout, &datain))) { - free(out->data); - out->data = NULL; - goto out; - } - key_krb5_to_lucid(&kout, out); - - out: - if (code) - printerr(0, "ERROR: derive_key_lucid returning error %d (%s)\n", - code, error_message(code)); - return (code); -} - -static int -prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, - gss_buffer_desc *buf) -{ - char *p, *end; - static int constant_zero = 0; - unsigned char fakeseed[16]; - uint32_t word_send_seq; - gss_krb5_lucid_key_t enc_key; - int i; - char *skd, *dkd; - gss_buffer_desc fakeoid; - - /* - * The new Kerberos interface to get the gss context - * does not include the seed or seed_init fields - * because we never really use them. But for now, - * send down a fake buffer so we can use the same - * interface to the kernel. - */ - memset(&enc_key, 0, sizeof(enc_key)); - memset(&fakeoid, 0, sizeof(fakeoid)); - - if (!(buf->value = calloc(1, MAX_CTX_LEN))) - goto out_err; - p = buf->value; - end = buf->value + MAX_CTX_LEN; - - if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err; - - /* seed_init and seed not used by kernel anyway */ - if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; - if (write_bytes(&p, end, &fakeseed, 16)) goto out_err; - - if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.sign_alg)) goto out_err; - if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.seal_alg)) goto out_err; - if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; - word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */ - if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err; - if (write_oid(&p, end, &krb5oid)) goto out_err; +/* for 3DES */ +#define KG_USAGE_SEAL 22 +#define KG_USAGE_SIGN 23 +#define KG_USAGE_SEQ 24 - printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with " - "enctype %d and length %d\n", - lctx->rfc1964_kd.ctx_key.type, - lctx->rfc1964_kd.ctx_key.length); +/* for rfc???? */ +#define KG_USAGE_ACCEPTOR_SEAL 22 +#define KG_USAGE_ACCEPTOR_SIGN 23 +#define KG_USAGE_INITIATOR_SEAL 24 +#define KG_USAGE_INITIATOR_SIGN 25 - /* derive the encryption key and copy it into buffer */ - enc_key.type = lctx->rfc1964_kd.ctx_key.type; - enc_key.length = lctx->rfc1964_kd.ctx_key.length; - if ((enc_key.data = calloc(1, enc_key.length)) == NULL) - goto out_err; - skd = (char *) lctx->rfc1964_kd.ctx_key.data; - dkd = (char *) enc_key.data; - for (i = 0; i < enc_key.length; i++) - dkd[i] = skd[i] ^ 0xf0; - if (write_lucid_keyblock(&p, end, &enc_key)) { - free(enc_key.data); - goto out_err; - } - free(enc_key.data); +/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */ +enum seal_alg { + SEAL_ALG_NONE = 0xffff, + SEAL_ALG_DES = 0x0000, + SEAL_ALG_1 = 0x0001, /* not published */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ + SEAL_ALG_DES3KD = 0x0002 +}; - if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key)) - goto out_err; +#define KEY_USAGE_SEED_ENCRYPTION 0xAA +#define KEY_USAGE_SEED_INTEGRITY 0x55 +#define KEY_USAGE_SEED_CHECKSUM 0x99 +#define K5CLENGTH 5 - buf->length = p - (char *)buf->value; - return 0; -out_err: - printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); - if (buf->value) { - free(buf->value); - buf->value = NULL; - } - buf->length = 0; - if (enc_key.data) { - free(enc_key.data); - enc_key.data = NULL; - } - return -1; -} +extern void krb5_enc_des3; +extern void krb5int_enc_des3; +extern void krb5int_enc_arcfour; +extern void krb5int_enc_aes128; +extern void krb5int_enc_aes256; +extern int krb5_derive_key(); /* - * Prepare a new-style buffer to send to the kernel for newer encryption - * types -- or for DES3. - * - * The new format is: + * XXX Hack alert! XXX Do NOT submit upstream! + * XXX Hack alert! XXX Do NOT submit upstream! * - * u32 version; This is two (2) - * s32 endtime; - * u32 flags; - * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 - * #define KRB5_CTX_FLAG_CFX 0x00000002 - * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 - * u64 seq_send; - * u32 enctype; ( encrption type of keys ) - * u32 size_of_each_key; ( size of each key in bytes ) - * u32 number_of_keys; ( N -- should always be 3 for now ) - * keydata-1; ( Ke ) - * keydata-2; ( Ki ) - * keydata-3; ( Kc ) + * We should be passing down a single key to the kernel + * and it should be deriving the other keys. We cannot + * depend on any of this stuff being accessible in the + * future. * + * XXX Hack alert! XXX Do NOT submit upstream! + * XXX Hack alert! XXX Do NOT submit upstream! */ -static int -prepare_krb5_ctx_v2_buffer(gss_krb5_lucid_context_v1_t *lctx, - gss_buffer_desc *buf) -{ - char *p, *end; - static uint32_t version = 2; - uint32_t v2_flags = 0; - gss_krb5_lucid_key_t enc_key; - gss_krb5_lucid_key_t derived_key; - gss_buffer_desc fakeoid; - uint32_t enctype; - uint32_t keysize; - uint32_t numkeys; - - memset(&enc_key, 0, sizeof(enc_key)); - memset(&fakeoid, 0, sizeof(fakeoid)); - - if (!(buf->value = calloc(1, MAX_CTX_LEN))) - goto out_err; - p = buf->value; - end = buf->value + MAX_CTX_LEN; - - /* Version 2 */ - if (WRITE_BYTES(&p, end , version)) goto out_err; - if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; - - if (lctx->initiate) - v2_flags |= KRB5_CTX_FLAG_INITIATOR; - if (lctx->protocol != 0) - v2_flags |= KRB5_CTX_FLAG_CFX; - if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1) - v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; - - if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; - - if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; - - /* Protocol 0 here implies DES3 or RC4 */ - if (lctx->protocol == 0) { - enctype = lctx->rfc1964_kd.ctx_key.type; - keysize = lctx->rfc1964_kd.ctx_key.length; - numkeys = 3; /* XXX is always gonna be three? */ - } else { - if (lctx->cfx_kd.have_acceptor_subkey) { - enctype = lctx->cfx_kd.acceptor_subkey.type; - keysize = lctx->cfx_kd.acceptor_subkey.length; - } else { - enctype = lctx->cfx_kd.ctx_key.type; - keysize = lctx->cfx_kd.ctx_key.length; - } - numkeys = 3; - } - printerr(2, "prepare_krb5_ctx_v2_buffer: serializing %d keys with " - "enctype %d and size %d\n", numkeys, enctype, keysize); - if (WRITE_BYTES(&p, end, enctype)) goto out_err; - if (WRITE_BYTES(&p, end, keysize)) goto out_err; - if (WRITE_BYTES(&p, end, numkeys)) goto out_err; - - if (lctx->protocol == 0) { - /* derive and send down: Ke, Ki, and Kc */ - /* Ke */ - if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, - lctx->rfc1964_kd.ctx_key.length)) - goto out_err; - - /* Ki */ - if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, - lctx->rfc1964_kd.ctx_key.length)) - goto out_err; - - /* Kc */ - if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, - &derived_key, - KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) - goto out_err; - if (write_bytes(&p, end, derived_key.data, - derived_key.length)) - goto out_err; - free(derived_key.data); - } else { - gss_krb5_lucid_key_t *keyptr; - uint32_t sign_usage, seal_usage; - - if (lctx->cfx_kd.have_acceptor_subkey) - keyptr = &lctx->cfx_kd.acceptor_subkey; - else - keyptr = &lctx->cfx_kd.ctx_key; - -#if 0 - if (lctx->initiate == 1) { - sign_usage = KG_USAGE_INITIATOR_SIGN; - seal_usage = KG_USAGE_INITIATOR_SEAL; - } else { - sign_usage = KG_USAGE_ACCEPTOR_SIGN; - seal_usage = KG_USAGE_ACCEPTOR_SEAL; - } -#else - /* FIXME - * These are from rfc4142, but I don't understand: if we supply - * different 'usage' value for client & server, then the peers - * will have different derived keys. How could this work? - * - * Here we simply use old SIGN/SEAL values until we find the - * answer. --ericm - * FIXME - */ - sign_usage = KG_USAGE_SIGN; - seal_usage = KG_USAGE_SEAL; -#endif - - /* derive and send down: Ke, Ki, and Kc */ - - /* Ke */ - if (derive_key_lucid(keyptr, &derived_key, - seal_usage, KEY_USAGE_SEED_ENCRYPTION)) - goto out_err; - if (write_bytes(&p, end, derived_key.data, - derived_key.length)) - goto out_err; - free(derived_key.data); - - /* Ki */ - if (derive_key_lucid(keyptr, &derived_key, - seal_usage, KEY_USAGE_SEED_INTEGRITY)) - goto out_err; - if (write_bytes(&p, end, derived_key.data, - derived_key.length)) - goto out_err; - free(derived_key.data); - - /* Kc */ - if (derive_key_lucid(keyptr, &derived_key, - sign_usage, KEY_USAGE_SEED_CHECKSUM)) - goto out_err; - if (write_bytes(&p, end, derived_key.data, - derived_key.length)) - goto out_err; - free(derived_key.data); - } - - buf->length = p - (char *)buf->value; - return 0; - -out_err: - printerr(0, "ERROR: prepare_krb5_ctx_v2_buffer: " - "failed serializing krb5 context for kernel\n"); - if (buf->value) { - free(buf->value); - buf->value = NULL; - } - buf->length = 0; - if (enc_key.data) { - free(enc_key.data); - enc_key.data = NULL; - } - return -1; -} - - -int -serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) -{ - OM_uint32 maj_stat, min_stat; - void *return_ctx = 0; - OM_uint32 vers; - gss_krb5_lucid_context_v1_t *lctx = 0; - int retcode = 0; - - printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n"); - maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx, - 1, &return_ctx); - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_export_lucid_sec_context", - maj_stat, min_stat, &krb5oid); - goto out_err; - } - - /* Check the version returned, we only support v1 right now */ - vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version; - switch (vers) { - case 1: - lctx = (gss_krb5_lucid_context_v1_t *) return_ctx; - break; - default: - printerr(0, "ERROR: unsupported lucid sec context version %d\n", - vers); - goto out_err; - break; - } - - /* - * Now lctx points to a lucid context that we can send down to kernel - * - * Note: we send down different information to the kernel depending - * on the protocol version and the enctyption type. - * For protocol version 0 with all enctypes besides DES3, we use - * the original format. For protocol version != 0 or DES3, we - * send down the new style information. - */ - - if (lctx->protocol == 0 && - lctx->rfc1964_kd.ctx_key.type == ENCTYPE_DES_CBC_RAW) - retcode = prepare_krb5_rfc1964_buffer(lctx, buf); - else - retcode = prepare_krb5_ctx_v2_buffer(lctx, buf); - - maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_export_lucid_sec_context", - maj_stat, min_stat, &krb5oid); - printerr(0, "WARN: failed to free lucid sec context\n"); - } - - if (retcode) { - printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer " - "failed (retcode = %d)\n", retcode); - goto out_err; - } - - return 0; - -out_err: - printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); - return -1; -} - - -#else /* HAVE_LUCID_CONTEXT_SUPPORT */ - -static int -write_keyblock(char **p, char *end, struct _krb5_keyblock *arg) -{ - gss_buffer_desc tmp; - - if (WRITE_BYTES(p, end, arg->enctype)) return -1; - tmp.length = arg->length; - tmp.value = arg->contents; - if (write_buffer(p, end, &tmp)) return -1; - return 0; -} - /* * Function to derive a new key from a given key and given constant data. */ @@ -631,19 +203,24 @@ derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra) int keylength; void *enc; - /* - * XXX Hack alert. We don't have "legal" access to these - * values and structures located in libk5crypto - */ switch (in->enctype) { +#ifdef ENCTYPE_DES3_CBC_RAW case ENCTYPE_DES3_CBC_RAW: keylength = 24; +/* Extra hack, the structure was renamed as rc4 was added... */ +#if defined(ENCTYPE_ARCFOUR_HMAC) enc = &krb5int_enc_des3; +#else + enc = &krb5_enc_des3; +#endif break; +#endif +#ifdef ENCTYPE_ARCFOUR_HMAC case ENCTYPE_ARCFOUR_HMAC: keylength = 16; enc = &krb5int_enc_arcfour; break; +#endif default: code = KRB5_BAD_ENCTYPE; goto out; @@ -711,7 +288,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) switch (kctx->sealalg) { case SEAL_ALG_DES: - /* Versions 0 and 1 */ + /* Old format of context to the kernel */ if (kctx->initiate) { if (WRITE_BYTES(&p, end, constant_one)) goto out_err; } @@ -742,8 +319,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) break; case SEAL_ALG_MICROSOFT_RC4: case SEAL_ALG_DES3KD: - /* u32 version; ( 2 ) - * s32 endtime; + /* New format of context to the kernel */ + /* s32 endtime; * u32 flags; * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 * #define KRB5_CTX_FLAG_CFX 0x00000002 @@ -756,11 +333,15 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) * keydata-2; ( Ki (Kseq for DES3) ) * keydata-3; ( Kc (derived checksum key) ) */ - /* Version 2 */ - if (WRITE_BYTES(&p, end , constant_two)) goto out_err; + if (kctx->initiate) { + if (WRITE_BYTES(&p, end, constant_one)) goto out_err; + } + else { + if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; + } if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; - /* Only applicable flag for is initiator */ + /* Only applicable flag for this is initiator */ if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR; if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; @@ -807,11 +388,11 @@ out_err: printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); if (buf->value) { free(buf->value); - buf->value = NULL; } + buf->value = NULL; buf->length = 0; return -1; } -#endif /* HAVE_LUCID_CONTEXT_SUPPORT */ #endif /* HAVE_KRB5 */ +#endif /* HAVE_LUCID_CONTEXT_SUPPORT */ diff --git a/lustre/utils/gss/gssd.c b/lustre/utils/gss/gssd.c index 137609b..78c895e 100644 --- a/lustre/utils/gss/gssd.c +++ b/lustre/utils/gss/gssd.c @@ -53,9 +53,11 @@ #include "krb5_util.h" #include "lsupport.h" -char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR; +char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR; +char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR; char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE; char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR; +int use_memcache = 0; void sig_die(int signal) @@ -91,17 +93,20 @@ main(int argc, char *argv[]) extern char *optarg; char *progname; - while ((opt = getopt(argc, argv, "fvrmp:k:d:")) != -1) { + while ((opt = getopt(argc, argv, "fvrmMp:k:d:")) != -1) { switch (opt) { case 'f': fg = 1; break; + case 'M': + use_memcache = 1; + break; case 'v': verbosity++; break; case 'p': - strncpy(pipefsdir, optarg, sizeof(pipefsdir)); - if (pipefsdir[sizeof(pipefsdir)-1] != '\0') + strncpy(pipefs_dir, optarg, sizeof(pipefs_dir)); + if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0') errx(1, "pipefs path name too long"); break; case 'k': @@ -130,11 +135,6 @@ main(int argc, char *argv[]) if (gssd_check_mechs() != 0) errx(1, "Problem with gssapi library"); -#if 0 - /* Determine Kerberos information from the kernel */ - gssd_obtain_kernel_krb5_info(); -#endif - if (!fg && daemon(0, 0) < 0) errx(1, "fork"); @@ -153,6 +153,11 @@ main(int argc, char *argv[]) signal(SIGTERM, sig_die); signal(SIGHUP, sig_hup); +#if 0 + /* Determine Kerberos information from the kernel */ + gssd_obtain_kernel_krb5_info(); +#endif + lgssd_run(); printerr(0, "gssd_run returned!\n"); abort(); diff --git a/lustre/utils/gss/gssd.h b/lustre/utils/gss/gssd.h index 0eeef3b..079bbc5 100644 --- a/lustre/utils/gss/gssd.h +++ b/lustre/utils/gss/gssd.h @@ -63,10 +63,11 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUTHTYPE_LIPKEY}; -extern char pipefsdir[PATH_MAX]; +extern char pipefs_dir[PATH_MAX]; extern char keytabfile[PATH_MAX]; extern char ccachedir[PATH_MAX]; extern char gethostname_ex[PATH_MAX]; +extern int use_memcache; TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list; diff --git a/lustre/utils/gss/gssd_main_loop.c b/lustre/utils/gss/gssd_main_loop.c index e87b4b3..d0a4b4f 100644 --- a/lustre/utils/gss/gssd_main_loop.c +++ b/lustre/utils/gss/gssd_main_loop.c @@ -106,9 +106,9 @@ lgssd_run() dn_act.sa_flags = SA_SIGINFO; sigaction(DNOTIFY_SIGNAL, &dn_act, NULL); - if ((fd = open(pipefsdir, O_RDONLY)) == -1) { + if ((fd = open(pipefs_dir, O_RDONLY)) == -1) { printerr(0, "ERROR: failed to open %s: %s\n", - pipefsdir, strerror(errno)); + pipefs_dir, strerror(errno)); exit(1); } fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL); @@ -118,8 +118,8 @@ lgssd_run() while (1) { while (dir_changed) { - printerr(2, "pipefs root dir changed\n"); dir_changed = 0; + printerr(2, "pipefs root dir changed\n"); if (update_client_list()) { printerr(0, "ERROR: couldn't update " "client list\n"); diff --git a/lustre/utils/gss/gssd_proc.c b/lustre/utils/gss/gssd_proc.c index e3bebb2..4f1d35a 100644 --- a/lustre/utils/gss/gssd_proc.c +++ b/lustre/utils/gss/gssd_proc.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -79,19 +80,19 @@ * with an index into pollarray[], and other basic data about that client. * * Directory structure: created by the kernel nfs client - * /pipefsdir/clntXX : one per rpc_clnt struct in the kernel - * /pipefsdir/clntXX/krb5 : read uid for which kernel wants - * a context, write the resulting context - * /pipefsdir/clntXX/info : stores info such as server name + * {pipefs_nfsdir}/clntXX : one per rpc_clnt struct in the kernel + * {pipefs_nfsdir}/clntXX/krb5 : read uid for which kernel wants + * a context, write the resulting context + * {pipefs_nfsdir}/clntXX/info : stores info such as server name * * Algorithm: - * Poll all /pipefsdir/clntXX/krb5 files. When ready, data read + * Poll all {pipefs_nfsdir}/clntXX/krb5 files. When ready, data read * is a uid; performs rpcsec_gss context initialization protocol to * get a cred for that user. Writes result to corresponding krb5 file * in a form the kernel code will understand. * In addition, we make sure we are notified whenever anything is - * created or destroyed in pipefsdir/ or in an of the clntXX directories, - * and rescan the whole pipefsdir when this happens. + * created or destroyed in {pipefs_nfsdir} or in an of the clntXX directories, + * and rescan the whole {pipefs_nfsdir} when this happens. */ struct pollfd * pollarray; @@ -101,6 +102,7 @@ int pollsize; /* the size of pollaray (in pollfd's) */ static void destroy_client(struct clnt_info *clp) { + printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd); if (clp->krb5_poll_index != -1) memset(&pollarray[clp->krb5_poll_index], 0, sizeof(struct pollfd)); @@ -306,13 +308,13 @@ update_client_list(void) struct stat statbuf; int i, j; - if (chdir(pipefsdir) < 0) { + if (chdir(pipefs_dir) < 0) { printerr(0, "ERROR: can't chdir to %s: %s\n", - pipefsdir, strerror(errno)); + pipefs_dir, strerror(errno)); return -1; } - snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefsdir, "lustre"); + snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre"); if (stat(lustre_dir, &statbuf) == 0) { namelist[0] = &lustre_dirent; j = 1; @@ -325,8 +327,7 @@ update_client_list(void) update_old_clients(namelist, j); for (i=0; i < j; i++) { - if (i < FD_ALLOC_BLOCK && - !find_client(namelist[i]->d_name)) + if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name)) process_clnt_dir(namelist[i]->d_name); } @@ -363,7 +364,7 @@ struct lustre_gss_data { static int do_downcall(int k5_fd, struct lgssd_upcall_data *updata, - struct lustre_gss_data *lgd, gss_buffer_desc *context_token) + struct lustre_gss_data *lgd, gss_buffer_desc *context_token) { char *buf = NULL, *p = NULL, *end = NULL; unsigned int timeout = 0; /* XXX decide on a reasonable value */ @@ -904,16 +905,26 @@ handle_krb5_upcall(struct clnt_info *clp) struct lustre_gss_data lgd; char **credlist = NULL; char **ccname; + int read_rc; printerr(2, "handling krb5 upcall\n"); memset(&lgd, 0, sizeof(lgd)); lgd.lgd_rpc_err = -EPERM; /* default error code */ - if (read(clp->krb5_fd, &updata, sizeof(updata)) != sizeof(updata)) { + read_rc = read(clp->krb5_fd, &updata, sizeof(updata)); + if (read_rc < 0) { printerr(0, "WARNING: failed reading from krb5 " "upcall pipe: %s\n", strerror(errno)); goto out; + } else if (read_rc != sizeof(updata)) { + printerr(0, "upcall data mismatch: length %d, expect %d\n", + read_rc, sizeof(updata)); + + if (read_rc >= 4) + goto out_return_error; + else + goto out; } printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, " diff --git a/lustre/utils/gss/krb5_util.c b/lustre/utils/gss/krb5_util.c index ec65554..3edd4de 100644 --- a/lustre/utils/gss/krb5_util.c +++ b/lustre/utils/gss/krb5_util.c @@ -235,6 +235,7 @@ gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d) struct dirent *best_match_dir = NULL; struct stat best_match_stat, tmp_stat; + memset(&best_match_stat, 0, sizeof(best_match_stat)); *d = NULL; n = scandir(ccachedir, &namelist, select_krb5_ccache, 0); if (n < 0) { @@ -340,6 +341,7 @@ gssd_get_single_krb5_cred(krb5_context context, char cc_name[BUFSIZ]; int code; time_t now = time(0); + char *cache_type; memset(&my_creds, 0, sizeof(my_creds)); @@ -382,7 +384,12 @@ gssd_get_single_krb5_cred(krb5_context context, * Initialize cache file which we're going to be using */ - snprintf(cc_name, sizeof(cc_name), "FILE:%s/%s%s_%s", + if (use_memcache) + cache_type = "MEMORY"; + else + cache_type = "FILE"; + snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", + cache_type, GSSD_DEFAULT_CRED_DIR, GSSD_DEFAULT_CRED_PREFIX, GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm); ple->endtime = my_creds.times.endtime; @@ -1073,7 +1080,7 @@ gssd_obtain_kernel_krb5_info(void) char enctype_file_name[128]; char buf[1024]; char enctypes[128]; - char extrainfo[1024]; + int nscanned; int fd; int use_default_enctypes = 0; int nbytes, numfields; @@ -1081,7 +1088,7 @@ gssd_obtain_kernel_krb5_info(void) int code; snprintf(enctype_file_name, sizeof(enctype_file_name), - "%s/%s", pipefsdir, "krb5_info"); + "%s/%s", pipefs_dir, "krb5_info"); if ((fd = open(enctype_file_name, O_RDONLY)) == -1) { printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: " @@ -1092,15 +1099,18 @@ gssd_obtain_kernel_krb5_info(void) use_default_enctypes = 1; goto do_the_parse; } - if ((nbytes = read(fd, buf, sizeof(buf))) == -1) { + memset(buf, 0, sizeof(buf)); + if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) { printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " "Error reading Kerberos encryption type " "information file '%s'; using defaults (%s).\n", enctype_file_name, default_enctypes); use_default_enctypes = 1; + close(fd); goto do_the_parse; } - numfields = sscanf(buf, "enctypes: %s\n%s", enctypes, extrainfo); + close(fd); + numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned); if (numfields < 1) { printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " "error parsing Kerberos encryption type " @@ -1109,11 +1119,10 @@ gssd_obtain_kernel_krb5_info(void) use_default_enctypes = 1; goto do_the_parse; } - if (numfields > 1) { - printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: " - "Extra information, '%s', from '%s' is ignored\n", - enctype_file_name, extrainfo); - use_default_enctypes = 1; + if (nbytes > nscanned) { + printerr(2, "gssd_obtain_kernel_krb5_info: " + "Ignoring extra information, '%s', from '%s'\n", + buf+nscanned, enctype_file_name); goto do_the_parse; } do_the_parse: diff --git a/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff b/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff index 4254ea1..34f9cd7 100644 --- a/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff +++ b/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff @@ -1,772 +1,271 @@ ---- nfs-utils-1.0.10/utils/gssd/gssd_proc.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/gssd_proc.c 2006-10-30 16:40:47.000000000 -0700 -@@ -43,7 +43,6 @@ - #endif - #include "config.h" - #include --#include - #include - #include - #include -@@ -68,6 +67,7 @@ - #include "gss_oids.h" - #include "krb5_util.h" - #include "context.h" -+#include "lsupport.h" - - /* - * pollarray: -@@ -98,83 +98,6 @@ - - int pollsize; /* the size of pollaray (in pollfd's) */ - --/* XXX buffer problems: */ --static int --read_service_info(char *info_file_name, char **servicename, char **servername, -- int *prog, int *vers, char **protocol) { --#define INFOBUFLEN 256 -- char buf[INFOBUFLEN]; -- static char dummy[128]; -- int nbytes; -- static char service[128]; -- static char address[128]; -- char program[16]; -- char version[16]; -- char protoname[16]; -- in_addr_t inaddr; -- int fd = -1; -- struct hostent *ent = NULL; -- int numfields; -- -- *servicename = *servername = *protocol = NULL; -- -- if ((fd = open(info_file_name, O_RDONLY)) == -1) { -- printerr(0, "ERROR: can't open %s: %s\n", info_file_name, -- strerror(errno)); -- goto fail; -- } -- if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1) -- goto fail; -- close(fd); -- -- numfields = sscanf(buf,"RPC server: %127s\n" -- "service: %127s %15s version %15s\n" -- "address: %127s\n" -- "protocol: %15s\n", -- dummy, -- service, program, version, -- address, -- protoname); -- -- if (numfields == 5) { -- strcpy(protoname, "tcp"); -- } else if (numfields != 6) { -- goto fail; -- } -- -- /* check service, program, and version */ -- if(memcmp(service, "nfs", 3)) return -1; -- *prog = atoi(program + 1); /* skip open paren */ -- *vers = atoi(version); -- if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4))) -- goto fail; -- -- /* create service name */ -- inaddr = inet_addr(address); -- if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) { -- printerr(0, "ERROR: can't resolve server %s name\n", address); -- goto fail; -- } -- if (!(*servername = calloc(strlen(ent->h_name) + 1, 1))) -- goto fail; -- memcpy(*servername, ent->h_name, strlen(ent->h_name)); -- snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name); -- if (!(*servicename = calloc(strlen(buf) + 1, 1))) -- goto fail; -- memcpy(*servicename, buf, strlen(buf)); -- -- if (!(*protocol = strdup(protoname))) -- goto fail; -- return 0; --fail: -- printerr(0, "ERROR: failed to read service info\n"); -- if (fd != -1) close(fd); -- if (*servername) free(*servername); -- if (*servicename) free(*servicename); -- if (*protocol) free(*protocol); -- return -1; --} +diff -rup nfs-utils-1.0.10.orig/configure.in nfs-utils-1.0.10/configure.in +--- nfs-utils-1.0.10.orig/configure.in 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/configure.in 2006-11-15 21:44:43.000000000 -0700 +@@ -17,61 +17,14 @@ AC_ARG_WITH(release, + RELEASE=$withval, + RELEASE=1) + AC_SUBST(RELEASE) +-AC_ARG_WITH(statedir, +- [ --with-statedir=/foo use state dir /foo [/var/lib/nfs]], +- statedir=$withval, +- statedir=/var/lib/nfs) +- AC_SUBST(statedir) +-AC_ARG_WITH(statduser, +- [AC_HELP_STRING([--with-statduser=rpcuser], +- [statd to run under @<:@rpcuser or nobody@:>@] +- )], +- statduser=$withval, +- if test "x$cross_compiling" = "xno"; then +- if grep -s '^rpcuser:' /etc/passwd > /dev/null; then +- statduser=rpcuser +- else +- statduser=nobody +- fi +- else +- statduser=nobody +- fi) +- AC_SUBST(statduser) +-AC_ARG_ENABLE(nfsv3, +- [AC_HELP_STRING([--enable-nfsv3], +- [enable support for NFSv3 @<:@default=yes@:>@])], +- enable_nfsv3=$enableval, +- enable_nfsv3=yes) +- if test "$enable_nfsv3" = yes; then +- AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in]) +- else +- enable_nfsv3= +- fi +- AC_SUBST(enable_nfsv3) +-AC_ARG_ENABLE(nfsv4, +- [AC_HELP_STRING([--enable-nfsv4], +- [enable support for NFSv4 @<:@default=yes@:>@])], +- enable_nfsv4=$enableval, +- enable_nfsv4=yes) +- if test "$enable_nfsv4" = yes; then +- AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in]) +- IDMAPD=idmapd +- else +- enable_nfsv4= +- IDMAPD= +- fi +- AC_SUBST(IDMAPD) +- AC_SUBST(enable_nfsv4) +- AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"]) + AC_ARG_ENABLE(gss, + [AC_HELP_STRING([--enable-gss], + [enable support for rpcsec_gss @<:@default=yes@:>@])], + enable_gss=$enableval, + enable_gss=yes) + if test "$enable_gss" = yes; then +- AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in]) +- GSSD=gssd +- SVCGSSD=svcgssd ++ GSSD=lgssd ++ SVCGSSD=lsvcgssd + else + enable_gss= + GSSD= +@@ -81,38 +34,6 @@ AC_ARG_ENABLE(gss, + AC_SUBST(SVCGSSD) + AC_SUBST(enable_gss) + AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"]) +-AC_ARG_ENABLE(kprefix, +- [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])], +- test "$enableval" = "yes" && kprefix=k, +- kprefix=) +- AC_SUBST(kprefix) +-AC_ARG_ENABLE(secure-statd, +- [AC_HELP_STRING([--enable-secure-statd], +- [Only lockd can use statd (security)])], +- test "$enableval" = "yes" && secure_statd=yes, +- secure_statd=no) +- if test "$secure_statd" = yes; then +- AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.]) +- fi +- AC_SUBST(secure_statd) +-AC_ARG_ENABLE(rquotad, +- [AC_HELP_STRING([--enable-rquotad], +- [enable rquotad @<:@default=yes@:>@])], +- enable_rquotad=$enableval, +- enable_rquotad=yes) +- if test "$enable_rquotad" = yes; then +- RQUOTAD=rquotad +- else +- RQUOTAD= +- fi +- AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"]) - - static void - destroy_client(struct clnt_info *clp) - { -@@ -189,8 +112,6 @@ - if (clp->spkm3_fd != -1) close(clp->spkm3_fd); - if (clp->dirname) free(clp->dirname); - if (clp->servicename) free(clp->servicename); -- if (clp->servername) free(clp->servername); -- if (clp->protocol) free(clp->protocol); - free(clp); - } - -@@ -220,7 +141,6 @@ - { - char kname[32]; - char sname[32]; -- char info_file_name[32]; - - if (clp->krb5_fd == -1) { - snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname); -@@ -232,13 +152,6 @@ - } - if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1)) - return -1; -- snprintf(info_file_name, sizeof(info_file_name), "%s/info", -- clp->dirname); -- if ((clp->servicename == NULL) && -- read_service_info(info_file_name, &clp->servicename, -- &clp->servername, &clp->prog, &clp->vers, -- &clp->protocol)) -- return -1; - return 0; - } - -@@ -272,6 +185,8 @@ - } - pollarray[clp->krb5_poll_index].fd = clp->krb5_fd; - pollarray[clp->krb5_poll_index].events |= POLLIN; -+ printerr(2, "monitoring krb5 channel under %s\n", -+ clp->dirname); - } - - if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) { -@@ -385,7 +300,10 @@ - int - update_client_list(void) - { -- struct dirent **namelist; -+ char lustre_dir[PATH_MAX]; -+ struct dirent lustre_dirent = { .d_name = "lustre" }; -+ struct dirent *namelist[1]; -+ struct stat statbuf; - int i, j; - - if (chdir(pipefsdir) < 0) { -@@ -394,45 +312,76 @@ - return -1; - } - -- j = scandir(pipefsdir, &namelist, NULL, alphasort); -- if (j < 0) { -- printerr(0, "ERROR: can't scandir %s: %s\n", -- pipefsdir, strerror(errno)); -- return -1; -+ snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefsdir, "lustre"); -+ if (stat(lustre_dir, &statbuf) == 0) { -+ namelist[0] = &lustre_dirent; -+ j = 1; -+ printerr(2, "re-processing lustre directory\n"); -+ } else { -+ namelist[0] = NULL; -+ j = 0; -+ printerr(2, "lustre directory not exist\n"); - } -+ - update_old_clients(namelist, j); - for (i=0; i < j; i++) { -- if (i < FD_ALLOC_BLOCK -- && !strncmp(namelist[i]->d_name, "clnt", 4) -- && !find_client(namelist[i]->d_name)) -+ if (i < FD_ALLOC_BLOCK && -+ !find_client(namelist[i]->d_name)) - process_clnt_dir(namelist[i]->d_name); -- free(namelist[i]); - } - -- free(namelist); -+ chdir("/"); - return 0; - } - -+/* Context creation response. */ -+struct lustre_gss_init_res { -+ gss_buffer_desc gr_ctx; /* context handle */ -+ u_int gr_major; /* major status */ -+ u_int gr_minor; /* minor status */ -+ u_int gr_win; /* sequence window */ -+ gss_buffer_desc gr_token; /* token */ -+}; -+ -+struct lustre_gss_data { -+ int lgd_established; -+ int lgd_lustre_svc; /* mds/oss */ -+ int lgd_uid; /* uid */ -+ char *lgd_uuid; /* client device uuid */ -+ gss_name_t lgd_name; /* service name */ -+ -+ gss_OID lgd_mech; /* mech OID */ -+ u_int lgd_req_flags; /* request flags */ -+ gss_cred_id_t lgd_cred; /* credential */ -+ gss_ctx_id_t lgd_ctx; /* session context */ -+ gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */ -+ uint32_t lgd_seq_win; /* sequence window */ -+ -+ int lgd_rpc_err; -+ int lgd_gss_err; -+}; -+ - static int --do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, -- gss_buffer_desc *context_token) -+do_downcall(int k5_fd, struct lgssd_upcall_data *updata, -+ struct lustre_gss_data *lgd, gss_buffer_desc *context_token) - { - char *buf = NULL, *p = NULL, *end = NULL; - unsigned int timeout = 0; /* XXX decide on a reasonable value */ - unsigned int buf_size = 0; - -- printerr(1, "doing downcall\n"); -- buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) + -- sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length + -+ printerr(2, "doing downcall\n"); -+ buf_size = sizeof(updata->seq) + sizeof(timeout) + -+ sizeof(lgd->lgd_seq_win) + -+ sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length + - sizeof(context_token->length) + context_token->length; - p = buf = malloc(buf_size); - end = buf + buf_size; - -- if (WRITE_BYTES(&p, end, uid)) goto out_err; -+ if (WRITE_BYTES(&p, end, updata->seq)) goto out_err; - /* Not setting any timeout for now: */ - if (WRITE_BYTES(&p, end, timeout)) goto out_err; -- if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err; -- if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err; -+ if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err; -+ if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err; - if (write_buffer(&p, end, context_token)) goto out_err; - - if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; -@@ -440,12 +389,13 @@ - return 0; - out_err: - if (buf) free(buf); -- printerr(0, "Failed to write downcall!\n"); -+ printerr(0, "ERROR: Failed to write downcall!\n"); - return -1; - } - - static int --do_error_downcall(int k5_fd, uid_t uid, int err) -+do_error_downcall(int k5_fd, struct lgssd_upcall_data *updata, -+ int rpc_err, int gss_err) - { - char buf[1024]; - char *p = buf, *end = buf + 1024; -@@ -454,11 +404,12 @@ - - printerr(1, "doing error downcall\n"); - -- if (WRITE_BYTES(&p, end, uid)) goto out_err; -+ if (WRITE_BYTES(&p, end, updata->seq)) goto out_err; - if (WRITE_BYTES(&p, end, timeout)) goto out_err; - /* use seq_win = 0 to indicate an error: */ - if (WRITE_BYTES(&p, end, zero)) goto out_err; -- if (WRITE_BYTES(&p, end, err)) goto out_err; -+ if (WRITE_BYTES(&p, end, rpc_err)) goto out_err; -+ if (WRITE_BYTES(&p, end, gss_err)) goto out_err; - - if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; - return 0; -@@ -467,6 +418,7 @@ - return -1; - } - -+#if 0 - /* - * Create an RPC connection and establish an authenticated - * gss context with a server. -@@ -658,7 +610,287 @@ - - goto out; - } -+#endif -+ -+static -+int do_negotiation(struct lustre_gss_data *lgd, -+ gss_buffer_desc *gss_token, -+ struct lustre_gss_init_res *gr, -+ int timeout) -+{ -+ char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel"; -+ struct lgssd_ioctl_param param; -+ struct passwd *pw; -+ int fd, ret; -+ char outbuf[8192]; -+ unsigned int *p; -+ int res; -+ -+ pw = getpwuid(lgd->lgd_uid); -+ if (!pw) { -+ printerr(0, "no uid %u in local user database\n", -+ lgd->lgd_uid); -+ return -1; -+ } -+ -+ param.version = GSSD_INTERFACE_VERSION; -+ param.uuid = lgd->lgd_uuid; -+ param.lustre_svc = lgd->lgd_lustre_svc; -+ param.uid = lgd->lgd_uid; -+ param.gid = pw->pw_gid; -+ param.send_token_size = gss_token->length; -+ param.send_token = (char *) gss_token->value; -+ param.reply_buf_size = sizeof(outbuf); -+ param.reply_buf = outbuf; -+ -+ fd = open(file, O_RDWR); -+ if (fd < 0) { -+ printerr(0, "can't open file %s\n", file); -+ return -1; -+ } -+ -+ ret = write(fd, ¶m, sizeof(param)); -+ -+ if (ret != sizeof(param)) { -+ printerr(0, "lustre ioctl err: %d\n", strerror(errno)); -+ close(fd); -+ return -1; -+ } -+ if (param.status) { -+ close(fd); -+ printerr(0, "status: %d (%s)\n", -+ param.status, strerror((int)param.status)); -+ if (param.status == -ETIMEDOUT) { -+ /* kernel return -ETIMEDOUT means the rpc timedout, -+ * we should notify the caller to reinitiate the -+ * gss negotiation, by return -ERESTART -+ */ -+ lgd->lgd_rpc_err = -ERESTART; -+ lgd->lgd_gss_err = 0; -+ } else { -+ lgd->lgd_rpc_err = param.status; -+ lgd->lgd_gss_err = 0; -+ } -+ return -1; -+ } -+ p = (unsigned int *)outbuf; -+ res = *p++; -+ gr->gr_major = *p++; -+ gr->gr_minor = *p++; -+ gr->gr_win = *p++; -+ -+ gr->gr_ctx.length = *p++; -+ gr->gr_ctx.value = malloc(gr->gr_ctx.length); -+ memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length); -+ p += (((gr->gr_ctx.length + 3) & ~3) / 4); -+ -+ gr->gr_token.length = *p++; -+ gr->gr_token.value = malloc(gr->gr_token.length); -+ memcpy(gr->gr_token.value, p, gr->gr_token.length); -+ p += (((gr->gr_token.length + 3) & ~3) / 4); -+ -+ printerr(2, "do_negotiation: receive handle len %d, token len %d\n", -+ gr->gr_ctx.length, gr->gr_token.length); -+ close(fd); -+ return 0; -+} -+ -+static -+int gssd_refresh_lgd(struct lustre_gss_data *lgd) -+{ -+ struct lustre_gss_init_res gr; -+ gss_buffer_desc *recv_tokenp, send_token; -+ OM_uint32 maj_stat, min_stat, call_stat, ret_flags; -+ -+ /* GSS context establishment loop. */ -+ memset(&gr, 0, sizeof(gr)); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ -+ for (;;) { -+ /* print the token we just received */ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ printerr(3, "The received token length %d\n", -+ recv_tokenp->length); -+ print_hexl(3, recv_tokenp->value, recv_tokenp->length); -+ } -+ -+ maj_stat = gss_init_sec_context(&min_stat, -+ lgd->lgd_cred, -+ &lgd->lgd_ctx, -+ lgd->lgd_name, -+ lgd->lgd_mech, -+ lgd->lgd_req_flags, -+ 0, /* time req */ -+ NULL, /* channel */ -+ recv_tokenp, -+ NULL, /* used mech */ -+ &send_token, -+ &ret_flags, -+ NULL); /* time rec */ -+ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ } -+ if (maj_stat != GSS_S_COMPLETE && -+ maj_stat != GSS_S_CONTINUE_NEEDED) { -+ pgsserr("gss_init_sec_context", maj_stat, min_stat, -+ lgd->lgd_mech); -+ break; -+ } -+ if (send_token.length != 0) { -+ memset(&gr, 0, sizeof(gr)); -+ -+ /* print the token we are about to send */ -+ printerr(3, "token being sent length %d\n", -+ send_token.length); -+ print_hexl(3, send_token.value, send_token.length); -+ -+ call_stat = do_negotiation(lgd, &send_token, &gr, 0); -+ gss_release_buffer(&min_stat, &send_token); -+ -+ if (call_stat != 0 || -+ (gr.gr_major != GSS_S_COMPLETE && -+ gr.gr_major != GSS_S_CONTINUE_NEEDED)) { -+ printerr(0, "call stat %d, major stat 0x%x\n", -+ (int)call_stat, gr.gr_major); -+ return -1; -+ } -+ -+ if (gr.gr_ctx.length != 0) { -+ if (lgd->lgd_rmt_ctx.value) -+ gss_release_buffer(&min_stat, -+ &lgd->lgd_rmt_ctx); -+ lgd->lgd_rmt_ctx = gr.gr_ctx; -+ } -+ if (gr.gr_token.length != 0) { -+ if (maj_stat != GSS_S_CONTINUE_NEEDED) -+ break; -+ recv_tokenp = &gr.gr_token; -+ } -+ } - -+ /* GSS_S_COMPLETE => check gss header verifier, -+ * usually checked in gss_validate -+ */ -+ if (maj_stat == GSS_S_COMPLETE) { -+ lgd->lgd_established = 1; -+ lgd->lgd_seq_win = gr.gr_win; -+ break; -+ } -+ } -+ /* End context negotiation loop. */ -+ if (!lgd->lgd_established) { -+ if (gr.gr_token.length != 0) -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ -+ printerr(0, "context negotiation failed\n"); -+ return -1; -+ } -+ -+ printerr(2, "successfully refreshed lgd\n"); -+ return 0; -+} -+ -+static -+int gssd_create_lgd(struct clnt_info *clp, -+ struct lustre_gss_data *lgd, -+ struct lgssd_upcall_data *updata, -+ int authtype) -+{ -+ gss_buffer_desc sname; -+ OM_uint32 maj_stat, min_stat; -+ int retval = -1; -+ -+ lgd->lgd_established = 0; -+ lgd->lgd_lustre_svc = updata->svc; -+ lgd->lgd_uid = updata->uid; -+ lgd->lgd_uuid = updata->obd; -+ -+ switch (authtype) { -+ case AUTHTYPE_KRB5: -+ lgd->lgd_mech = (gss_OID) &krb5oid; -+ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ case AUTHTYPE_SPKM3: -+ lgd->lgd_mech = (gss_OID) &spkm3oid; -+ /* XXX sec.req_flags = GSS_C_ANON_FLAG; -+ * Need a way to switch.... -+ */ -+ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ default: -+ printerr(0, "Invalid authentication type (%d)\n", authtype); -+ return -1; -+ } -+ -+ lgd->lgd_cred = GSS_C_NO_CREDENTIAL; -+ lgd->lgd_ctx = GSS_C_NO_CONTEXT; -+ lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER; -+ lgd->lgd_seq_win = 0; -+ -+ sname.value = clp->servicename; -+ sname.length = strlen(clp->servicename); -+ -+ maj_stat = gss_import_name(&min_stat, &sname, -+ (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, -+ &lgd->lgd_name); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr(0, maj_stat, min_stat, lgd->lgd_mech); -+ goto out_fail; -+ } -+ -+ retval = gssd_refresh_lgd(lgd); -+ -+ if (lgd->lgd_name != GSS_C_NO_NAME) -+ gss_release_name(&min_stat, &lgd->lgd_name); -+ -+ if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL) -+ gss_release_cred(&min_stat, &lgd->lgd_cred); -+ -+ out_fail: -+ return retval; -+} -+ -+static -+void gssd_free_lgd(struct lustre_gss_data *lgd) -+{ -+ gss_buffer_t token = GSS_C_NO_BUFFER; -+ OM_uint32 maj_stat, min_stat; -+ -+ if (lgd->lgd_ctx == GSS_C_NO_CONTEXT) -+ return; -+ -+ maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token); -+} -+ -+static -+int construct_service_name(struct clnt_info *clp, -+ struct lgssd_upcall_data *ud) -+{ -+ const int buflen = 256; -+ char name[buflen]; -+ -+ if (clp->servicename) { -+ free(clp->servicename); -+ clp->servicename = NULL; -+ } -+ -+ if (lnet_nid2hostname(ud->nid, name, buflen)) -+ return -1; -+ -+ clp->servicename = malloc(32 + strlen(name)); -+ if (!clp->servicename) { -+ printerr(0, "can't alloc memory\n"); -+ return -1; -+ } -+ sprintf(clp->servicename, "%s@%s", -+ ud->svc == LUSTRE_GSS_SVC_MDS ? -+ GSSD_SERVICE_MDS : GSSD_SERVICE_OSS, -+ name); -+ printerr(2, "constructed servicename: %s\n", clp->servicename); -+ return 0; -+} - - /* - * this code uses the userland rpcsec gss library to create a krb5 -@@ -667,27 +899,53 @@ - void - handle_krb5_upcall(struct clnt_info *clp) - { -- uid_t uid; -- CLIENT *rpc_clnt = NULL; -- AUTH *auth = NULL; -- struct authgss_private_data pd; -- gss_buffer_desc token; -+ gss_buffer_desc token = { 0, NULL }; -+ struct lgssd_upcall_data updata; -+ struct lustre_gss_data lgd; - char **credlist = NULL; - char **ccname; - -- printerr(1, "handling krb5 upcall\n"); -+ printerr(2, "handling krb5 upcall\n"); - -- token.length = 0; -- token.value = NULL; -- memset(&pd, 0, sizeof(struct authgss_private_data)); -+ memset(&lgd, 0, sizeof(lgd)); -+ lgd.lgd_rpc_err = -EPERM; /* default error code */ - -- if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) { -- printerr(0, "WARNING: failed reading uid from krb5 " -+ if (read(clp->krb5_fd, &updata, sizeof(updata)) != sizeof(updata)) { -+ printerr(0, "WARNING: failed reading from krb5 " - "upcall pipe: %s\n", strerror(errno)); - goto out; - } +-AC_ARG_ENABLE(mount, +- [AC_HELP_STRING([--enable-mount], +- [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])], +- enable_mount=$enableval, +- enable_mount=no) +- AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"]) -- if (uid == 0) { -+ printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, " -+ "pag %llx, obd %s\n", updata.seq, updata.uid, updata.svc, -+ updata.nid, updata.pag, updata.obd); -+ -+ /* XXX in kernel pag is defined as "unsigned long", which might -+ * not keep original signed value after converted to u64. -+ */ -+ if (updata.pag != updata.uid && -+ ((updata.pag == 0xffffffffffffffffULL) || -+ (updata.pag == 0xffffffff))) { -+ printerr(0, "uid %u: pag %llx not allowed\n", -+ updata.uid, updata.pag); -+ lgd.lgd_rpc_err = -EPROTO; -+ goto out_return_error; -+ } -+ -+ if (updata.svc != LUSTRE_GSS_SVC_MDS && -+ updata.svc != LUSTRE_GSS_SVC_OSS) { -+ printerr(0, "invalid svc %d\n", updata.svc); -+ lgd.lgd_rpc_err = -EPROTO; -+ goto out_return_error; -+ } -+ updata.obd[sizeof(updata.obd)-1] = '\0'; -+ -+ if (construct_service_name(clp, &updata)) { -+ printerr(0, "failed to construct service name\n"); -+ goto out_return_error; -+ } -+ -+ if (updata.uid == 0) { - int success = 0; + # Check whether user wants TCP wrappers support + AC_TCP_WRAPPERS +@@ -155,47 +76,17 @@ AC_CHECK_FUNC(connect, , + AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL)) - /* -@@ -695,75 +953,66 @@ - * of them until one works or we've tried them all - */ - if (gssd_get_krb5_machine_cred_list(&credlist)) { -- printerr(0, "WARNING: Failed to obtain machine " -- "credentials for connection to " -- "server %s\n", clp->servername); -- goto out_return_error; -+ printerr(0, "ERROR: Failed to obtain machine " -+ "credentials for %s\n", clp->servicename); -+ goto out_return_error; - } - for (ccname = credlist; ccname && *ccname; ccname++) { - gssd_setup_krb5_machine_gss_ccache(*ccname); -- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, -- AUTHTYPE_KRB5)) == 0) { -+ if ((gssd_create_lgd(clp, &lgd, &updata, -+ AUTHTYPE_KRB5)) == 0) { - /* Success! */ - success++; - break; - } - printerr(2, "WARNING: Failed to create krb5 context " - "for user with uid %d with credentials " -- "cache %s for server %s\n", -- uid, *ccname, clp->servername); -+ "cache %s for service %s\n", -+ updata.uid, *ccname, clp->servicename); - } - gssd_free_krb5_machine_cred_list(credlist); - if (!success) { -- printerr(0, "WARNING: Failed to create krb5 context " -+ printerr(0, "ERROR: Failed to create krb5 context " - "for user with uid %d with any " -- "credentials cache for server %s\n", -- uid, clp->servername); -+ "credentials cache for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - } - else { - /* Tell krb5 gss which credentials cache to use */ -- gssd_setup_krb5_user_gss_ccache(uid, clp->servername); -+ gssd_setup_krb5_user_gss_ccache(updata.pag, updata.uid, -+ clp->servicename); + AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"]) +-if test "$enable_nfsv4" = yes; then +- AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support])) +- AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) +- AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support])) +- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) +- dnl librpcsecgss already has a dependency on libgssapi, +- dnl but we need to make sure we get the right version + if test "$enable_gss" = yes; then +- PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, , +- [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss. If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig]) +- ] +- ) + PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9) + fi -- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, -- AUTHTYPE_KRB5)) != 0) { -+ if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) { - printerr(0, "WARNING: Failed to create krb5 context " -- "for user with uid %d for server %s\n", -- uid, clp->servername); -+ "for user with uid %d for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - } +-fi +-if test "$knfsd_cv_glibc2" = no; then +- AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"]) +-fi + AC_SUBST(LIBSOCKET) + AC_SUBST(LIBCRYPT) + AC_SUBST(LIBBSD) -- if (!authgss_get_private_data(auth, &pd)) { -- printerr(0, "WARNING: Failed to obtain authentication " -- "data for user with uid %d for server %s\n", -- uid, clp->servername); -- goto out_return_error; -- } + if test "$enable_gss" = yes; then +- dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c +- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support])) +- AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support])) +- dnl the nfs4_set_debug function doesn't appear in all version of the library +- AC_CHECK_LIB(nfsidmap, nfs4_set_debug, +- AC_DEFINE(HAVE_NFS4_SET_DEBUG,1, +- [Whether nfs4_set_debug() is present in libnfsidmap]),) - -- if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) { -+ if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) { - printerr(0, "WARNING: Failed to serialize krb5 context for " -- "user with uid %d for server %s\n", -- uid, clp->servername); -+ "user with uid %d for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } + dnl Check for Kerberos V5 + AC_KERBEROS_V5 +- +- dnl This is not done until here because we need to have KRBLIBS set +- dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS) +- AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl) +- AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level, +- AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl) +- + fi -- do_downcall(clp->krb5_fd, uid, &pd, &token); -+ printerr(1, "refreshed: %u@%s for %s\n", -+ updata.uid, updata.obd, clp->servicename); -+ do_downcall(clp->krb5_fd, &updata, &lgd, &token); + dnl ************************************************************* +@@ -307,35 +198,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac - out: - if (token.value) - free(token.value); -- if (pd.pd_ctx_hndl.length != 0) -- authgss_free_private_data(&pd); -- if (auth) -- AUTH_DESTROY(auth); -- if (rpc_clnt) -- clnt_destroy(rpc_clnt); -+ -+ gssd_free_lgd(&lgd); - return; + AC_CONFIG_FILES([ + Makefile +- linux-nfs/Makefile +- support/Makefile +- support/export/Makefile +- support/include/nfs/Makefile +- support/include/rpcsvc/Makefile +- support/include/sys/fs/Makefile +- support/include/sys/Makefile +- support/include/Makefile +- support/misc/Makefile +- support/nfs/Makefile +- tools/Makefile +- tools/getiversion/Makefile +- tools/getkversion/Makefile +- tools/locktest/Makefile +- tools/nlmtest/Makefile +- tools/rpcdebug/Makefile +- tools/rpcgen/Makefile + utils/Makefile +- utils/exportfs/Makefile +- utils/gssd/Makefile +- utils/idmapd/Makefile +- utils/lockd/Makefile +- utils/mount/Makefile +- utils/mountd/Makefile +- utils/nfsd/Makefile +- utils/nfsstat/Makefile +- utils/nhfsstone/Makefile +- utils/rquotad/Makefile +- utils/showmount/Makefile +- utils/statd/Makefile]) ++ utils/gssd/Makefile]) + AC_OUTPUT - out_return_error: -- do_error_downcall(clp->krb5_fd, uid, -1); -+ do_error_downcall(clp->krb5_fd, &updata, -+ lgd.lgd_rpc_err, lgd.lgd_gss_err); - goto out; - } +diff -rup nfs-utils-1.0.10.orig/Makefile.am nfs-utils-1.0.10/Makefile.am +--- nfs-utils-1.0.10.orig/Makefile.am 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/Makefile.am 2006-11-15 21:44:43.000000000 -0700 +@@ -1,6 +1,6 @@ + ## Process this file with automake to produce Makefile.in -@@ -774,6 +1023,7 @@ - void - handle_spkm3_upcall(struct clnt_info *clp) - { -+#if 0 - uid_t uid; - CLIENT *rpc_clnt = NULL; - AUTH *auth = NULL; -@@ -825,4 +1075,5 @@ - out_return_error: - do_error_downcall(clp->spkm3_fd, uid, -1); - goto out; -+#endif +-SUBDIRS = tools support utils linux-nfs ++SUBDIRS = utils + + MAINTAINERCLEANFILES = Makefile.in + +diff -rup nfs-utils-1.0.10.orig/utils/gssd/cacheio.c nfs-utils-1.0.10/utils/gssd/cacheio.c +--- nfs-utils-1.0.10.orig/utils/gssd/cacheio.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/cacheio.c 2006-11-15 21:44:43.000000000 -0700 +@@ -227,7 +227,8 @@ int qword_get(char **bpp, char *dest, in + return -1; + while (*bp == ' ') bp++; + *bpp = bp; +- *dest = '\0'; ++// why should we clear *dest??? ++// *dest = '\0'; + return len; } ---- nfs-utils-1.0.10/utils/gssd/context_mit.c.lustre 2006-10-30 16:40:17.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/context_mit.c 2006-10-30 16:40:47.000000000 -0700 -@@ -34,8 +34,6 @@ + +diff -rup nfs-utils-1.0.10.orig/utils/gssd/context.c nfs-utils-1.0.10/utils/gssd/context.c +--- nfs-utils-1.0.10.orig/utils/gssd/context.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/context.c 2006-11-15 21:44:43.000000000 -0700 +@@ -33,8 +33,6 @@ + #include #include - #include #include -#include -#include #include "gss_util.h" #include "gss_oids.h" #include "err_util.h" -@@ -468,6 +466,7 @@ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/context.h nfs-utils-1.0.10/utils/gssd/context.h +--- nfs-utils-1.0.10.orig/utils/gssd/context.h 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/context.h 2006-11-15 21:44:43.000000000 -0700 +@@ -31,8 +31,6 @@ + #ifndef _CONTEXT_H_ + #define _CONTEXT_H_ + +-#include +- + /* Hopefully big enough to hold any serialized context */ + #define MAX_CTX_LEN 4096 + +diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_lucid.c nfs-utils-1.0.10/utils/gssd/context_lucid.c +--- nfs-utils-1.0.10.orig/utils/gssd/context_lucid.c 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/context_lucid.c 2006-11-15 21:44:43.000000000 -0700 +@@ -41,11 +41,7 @@ + #include + #include + #include +-#include "gss_util.h" +-#include "gss_oids.h" +-#include "err_util.h" +-#include "context.h" +- ++#include + #include + #include + #ifndef OM_uint64 +@@ -53,6 +49,11 @@ typedef uint64_t OM_uint64; + #endif + #include + ++#include "gss_util.h" ++#include "gss_oids.h" ++#include "err_util.h" ++#include "context.h" ++ + static int + write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) + { +@@ -451,6 +452,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc else keyptr = &lctx->cfx_kd.ctx_key; @@ -774,7 +273,7 @@ if (lctx->initiate == 1) { sign_usage = KG_USAGE_INITIATOR_SIGN; seal_usage = KG_USAGE_INITIATOR_SEAL; -@@ -475,6 +474,19 @@ +@@ -458,6 +460,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc sign_usage = KG_USAGE_ACCEPTOR_SIGN; seal_usage = KG_USAGE_ACCEPTOR_SEAL; } @@ -794,491 +293,1068 @@ /* derive and send down: Ke, Ki, and Kc */ -@@ -793,7 +805,10 @@ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_spkm3.c nfs-utils-1.0.10/utils/gssd/context_spkm3.c +--- nfs-utils-1.0.10.orig/utils/gssd/context_spkm3.c 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2006-11-15 21:44:43.000000000 -0700 +@@ -33,8 +33,6 @@ + #include + #include + #include +-#include +-#include + #include "gss_util.h" + #include "gss_oids.h" + #include "err_util.h" +diff -rup nfs-utils-1.0.10.orig/utils/gssd/err_util.c nfs-utils-1.0.10/utils/gssd/err_util.c +--- nfs-utils-1.0.10.orig/utils/gssd/err_util.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/err_util.c 2006-11-15 21:44:43.000000000 -0700 +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + #include "err_util.h" - out_err: - printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); -- if (buf->value) free(buf->value); -+ if (buf->value) { -+ free(buf->value); -+ buf->value = NULL; -+ } - buf->length = 0; - return -1; + static int verbosity = 0; +@@ -91,3 +93,40 @@ printit: + /* reset the buffer */ + memset(message_buf, 0, sizeof(message_buf)); } ---- nfs-utils-1.0.10/utils/gssd/context.h.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/context.h 2006-10-30 16:40:47.000000000 -0700 -@@ -31,8 +31,6 @@ - #ifndef _CONTEXT_H_ - #define _CONTEXT_H_ ++ ++void print_hexl(int pri, unsigned char *cp, int length) ++{ ++ int i, j, jm; ++ unsigned char c; ++ ++ printerr(pri, "length %d\n",length); ++ printerr(pri, "\n"); ++ ++ for (i = 0; i < length; i += 0x10) { ++ printerr(pri, " %04x: ", (u_int)i); ++ jm = length - i; ++ jm = jm > 16 ? 16 : jm; ++ ++ for (j = 0; j < jm; j++) { ++ if ((j % 2) == 1) ++ printerr(pri,"%02x ", (u_int)cp[i+j]); ++ else ++ printerr(pri,"%02x", (u_int)cp[i+j]); ++ } ++ for (; j < 16; j++) { ++ if ((j % 2) == 1) ++ printerr(pri," "); ++ else ++ printerr(pri," "); ++ } ++ printerr(pri," "); ++ ++ for (j = 0; j < jm; j++) { ++ c = cp[i+j]; ++ c = isprint(c) ? c : '.'; ++ printerr(pri,"%c", c); ++ } ++ printerr(pri,"\n"); ++ } ++} ++ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/err_util.h nfs-utils-1.0.10/utils/gssd/err_util.h +--- nfs-utils-1.0.10.orig/utils/gssd/err_util.h 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/err_util.h 2006-11-15 21:44:43.000000000 -0700 +@@ -33,5 +33,6 @@ --#include -- - int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf, - gss_OID mech); - int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf); ---- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c 2006-10-30 16:40:47.000000000 -0700 -@@ -94,7 +94,7 @@ - }; + void initerr(char *progname, int verbosity, int fg); + void printerr(int priority, char *format, ...); ++void print_hexl(int pri, unsigned char *cp, int length); - void --gssd_run() -+lgssd_run() - { - int ret; - struct sigaction dn_act; -@@ -118,6 +118,7 @@ + #endif /* _ERR_UTIL_H_ */ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c +--- nfs-utils-1.0.10.orig/utils/gssd/gss_clnt_send_err.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c 2006-11-15 21:44:43.000000000 -0700 +@@ -47,6 +47,7 @@ + #include "gssd.h" + #include "write_bytes.h" - while (1) { - while (dir_changed) { -+ printerr(2, "pipefs root dir changed\n"); - dir_changed = 0; - if (update_client_list()) { - printerr(0, "ERROR: couldn't update " ---- nfs-utils-1.0.10/utils/gssd/svcgssd.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/svcgssd.c 2006-10-30 16:40:47.000000000 -0700 -@@ -43,7 +43,6 @@ - #include - #include ++#if 0 + char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR; + + static void +@@ -102,3 +103,4 @@ main(int argc, char *argv[]) + } + exit(0); + } ++#endif +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd.c nfs-utils-1.0.10/utils/gssd/gssd.c +--- nfs-utils-1.0.10.orig/utils/gssd/gssd.c 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/gssd.c 2006-11-15 21:44:43.000000000 -0700 +@@ -40,7 +40,6 @@ + + #include #include -#include - #include - #include -@@ -54,11 +53,33 @@ - #include - #include - #include --#include "nfslib.h" -+#include - #include "svcgssd.h" - #include "gss_util.h" + #include + #include +@@ -52,6 +51,7 @@ #include "err_util.h" + #include "gss_util.h" + #include "krb5_util.h" +#include "lsupport.h" -+void -+closeall(int min) -+{ -+ DIR *dir = opendir("/proc/self/fd"); -+ if (dir != NULL) { -+ int dfd = dirfd(dir); -+ struct dirent *d; -+ -+ while ((d = readdir(dir)) != NULL) { -+ char *endp; -+ long n = strtol(d->d_name, &endp, 10); -+ if (*endp != '\0' && n >= min && n != dfd) -+ (void) close(n); -+ } -+ closedir(dir); -+ } else { -+ int fd = sysconf(_SC_OPEN_MAX); -+ while (--fd >= min) -+ (void) close(fd); -+ } -+} - /* - * mydaemon creates a pipe between the partent and child - * process. The parent process will wait until the -@@ -165,8 +186,8 @@ - int get_creds = 1; + char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR; + char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR; +@@ -79,7 +79,7 @@ sig_hup(int signal) + static void + usage(char *progname) + { +- fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", ++ fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", + progname); + exit(1); + } +@@ -89,7 +89,6 @@ main(int argc, char *argv[]) + { int fg = 0; int verbosity = 0; - int rpc_verbosity = 0; int opt; -+ int must_srv_mds = 0, must_srv_oss = 0; extern char *optarg; char *progname; - -@@ -181,8 +202,13 @@ +@@ -99,18 +98,12 @@ main(int argc, char *argv[]) + case 'f': + fg = 1; + break; +- case 'm': +- /* Accept but ignore this. Now the default. */ +- break; + case 'M': + use_memcache = 1; + break; case 'v': verbosity++; break; - case 'r': - rpc_verbosity++; -+ case 'm': -+ get_creds = 1; -+ must_srv_mds = 1; -+ break; -+ case 'o': -+ get_creds = 1; -+ must_srv_oss = 1; +- break; + case 'p': + strncpy(pipefs_dir, optarg, sizeof(pipefs_dir)); + if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0') +@@ -131,10 +124,6 @@ main(int argc, char *argv[]) break; - default: - usage(argv[0]); -@@ -196,27 +222,13 @@ + } + } +- snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s", +- pipefs_dir, GSSD_SERVICE_NAME); +- if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0') +- errx(1, "pipefs_nfsdir path name too long"); + + if ((progname = strrchr(argv[0], '/'))) + progname++; +@@ -142,13 +131,6 @@ main(int argc, char *argv[]) progname = argv[0]; initerr(progname, verbosity, fg); -#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL - authgss_set_debug_level(rpc_verbosity); -#else -- if (rpc_verbosity > 0) +- if (rpc_verbosity > 0) - printerr(0, "Warning: rpcsec_gss library does not " - "support setting debug level\n"); -#endif - if (gssd_check_mechs() != 0) { - printerr(0, "ERROR: Problem with gssapi library\n"); + if (gssd_check_mechs() != 0) + errx(1, "Problem with gssapi library"); +@@ -156,16 +138,27 @@ main(int argc, char *argv[]) + if (!fg && daemon(0, 0) < 0) + errx(1, "fork"); + ++ /* This should be checked _after_ daemon(), because we need to own ++ * the undo-able semaphore by this process ++ */ ++ gssd_init_unique(GSSD_CLI); ++ ++ /* Process keytab file and get machine credentials. This will modify ++ * disk status so do it after we are sure we are the only instance ++ */ ++ if (gssd_refresh_krb5_machine_creds()) ++ return -1; ++ + signal(SIGINT, sig_die); + signal(SIGTERM, sig_die); + signal(SIGHUP, sig_hup); + +- /* Process keytab file and get machine credentials */ +- gssd_refresh_krb5_machine_creds(); ++#if 0 + /* Determine Kerberos information from the kernel */ + gssd_obtain_kernel_krb5_info(); ++#endif + +- gssd_run(); ++ lgssd_run(); + printerr(0, "gssd_run returned!\n"); + abort(); + } +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd.h nfs-utils-1.0.10/utils/gssd/gssd.h +--- nfs-utils-1.0.10.orig/utils/gssd/gssd.h 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/gssd.h 2006-11-15 21:44:43.000000000 -0700 +@@ -48,8 +48,13 @@ + #define GSSD_DEFAULT_CRED_PREFIX "krb5cc_" + #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine" + #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab" +-#define GSSD_SERVICE_NAME "nfs" +-#define GSSD_SERVICE_NAME_LEN 3 ++#define GSSD_SERVICE_MDS "lustre_mds" ++#define GSSD_SERVICE_OSS "lustre_oss" ++#define GSSD_SERVICE_MDS_NAMELEN 10 ++#define GSSD_SERVICE_OSS_NAMELEN 10 ++ ++#define LUSTRE_ROOT_NAME "lustre_root" ++#define LUSTRE_ROOT_NAMELEN 11 + + /* + * The gss mechanisms that we can handle +@@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT + + + extern char pipefs_dir[PATH_MAX]; +-extern char pipefs_nfsdir[PATH_MAX]; + extern char keytabfile[PATH_MAX]; + extern char ccachedir[PATH_MAX]; ++extern char gethostname_ex[PATH_MAX]; + extern int use_memcache; + + TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list; +@@ -71,10 +76,6 @@ struct clnt_info { + char *dirname; + int dir_fd; + char *servicename; +- char *servername; +- int prog; +- int vers; +- char *protocol; + int krb5_fd; + int krb5_poll_index; + int spkm3_fd; +@@ -85,8 +86,7 @@ void init_client_list(void); + int update_client_list(void); + void handle_krb5_upcall(struct clnt_info *clp); + void handle_spkm3_upcall(struct clnt_info *clp); +-int gssd_acquire_cred(char *server_name); +-void gssd_run(void); ++void lgssd_run(void); + + + #endif /* _RPC_GSSD_H_ */ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c +--- nfs-utils-1.0.10.orig/utils/gssd/gssd_main_loop.c 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c 2006-11-15 21:44:43.000000000 -0700 +@@ -94,7 +94,7 @@ scan_poll_results(int ret) + }; + + void +-gssd_run() ++lgssd_run() + { + int ret; + struct sigaction dn_act; +@@ -106,9 +106,9 @@ gssd_run() + dn_act.sa_flags = SA_SIGINFO; + sigaction(DNOTIFY_SIGNAL, &dn_act, NULL); + +- if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) { ++ if ((fd = open(pipefs_dir, O_RDONLY)) == -1) { + printerr(0, "ERROR: failed to open %s: %s\n", +- pipefs_nfsdir, strerror(errno)); ++ pipefs_dir, strerror(errno)); exit(1); } + fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL); +@@ -119,6 +119,7 @@ gssd_run() + while (1) { + while (dir_changed) { + dir_changed = 0; ++ printerr(2, "pipefs root dir changed\n"); + if (update_client_list()) { + printerr(0, "ERROR: couldn't update " + "client list\n"); +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd_proc.c nfs-utils-1.0.10/utils/gssd/gssd_proc.c +--- nfs-utils-1.0.10.orig/utils/gssd/gssd_proc.c 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/gssd_proc.c 2006-11-15 21:44:43.000000000 -0700 +@@ -43,7 +43,6 @@ + #endif + #include "config.h" + #include +-#include + #include + #include + #include +@@ -69,6 +68,7 @@ + #include "gss_oids.h" + #include "krb5_util.h" + #include "context.h" ++#include "lsupport.h" -- if (!fg) -- mydaemon(0, 0); + /* + * pollarray: +@@ -99,86 +99,10 @@ struct pollfd * pollarray; + + int pollsize; /* the size of pollaray (in pollfd's) */ + +-/* XXX buffer problems: */ +-static int +-read_service_info(char *info_file_name, char **servicename, char **servername, +- int *prog, int *vers, char **protocol) { +-#define INFOBUFLEN 256 +- char buf[INFOBUFLEN]; +- static char dummy[128]; +- int nbytes; +- static char service[128]; +- static char address[128]; +- char program[16]; +- char version[16]; +- char protoname[16]; +- in_addr_t inaddr; +- int fd = -1; +- struct hostent *ent = NULL; +- int numfields; - -- signal(SIGINT, sig_die); -- signal(SIGTERM, sig_die); -- signal(SIGHUP, sig_hup); +- *servicename = *servername = *protocol = NULL; - -- if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) { -+ if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) { - printerr(0, "unable to obtain root (machine) credentials\n"); - printerr(0, "do you have a keytab entry for " - "nfs/@ in " -@@ -225,9 +237,18 @@ - } +- if ((fd = open(info_file_name, O_RDONLY)) == -1) { +- printerr(0, "ERROR: can't open %s: %s\n", info_file_name, +- strerror(errno)); +- goto fail; +- } +- if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1) +- goto fail; +- close(fd); +- +- numfields = sscanf(buf,"RPC server: %127s\n" +- "service: %127s %15s version %15s\n" +- "address: %127s\n" +- "protocol: %15s\n", +- dummy, +- service, program, version, +- address, +- protoname); +- +- if (numfields == 5) { +- strcpy(protoname, "tcp"); +- } else if (numfields != 6) { +- goto fail; +- } +- +- /* check service, program, and version */ +- if(memcmp(service, "nfs", 3)) return -1; +- *prog = atoi(program + 1); /* skip open paren */ +- *vers = atoi(version); +- if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4))) +- goto fail; +- +- /* create service name */ +- inaddr = inet_addr(address); +- if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) { +- printerr(0, "ERROR: can't resolve server %s name\n", address); +- goto fail; +- } +- if (!(*servername = calloc(strlen(ent->h_name) + 1, 1))) +- goto fail; +- memcpy(*servername, ent->h_name, strlen(ent->h_name)); +- snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name); +- if (!(*servicename = calloc(strlen(buf) + 1, 1))) +- goto fail; +- memcpy(*servicename, buf, strlen(buf)); +- +- if (!(*protocol = strdup(protoname))) +- goto fail; +- return 0; +-fail: +- printerr(0, "ERROR: failed to read service info\n"); +- if (fd != -1) close(fd); +- if (*servername) free(*servername); +- if (*servicename) free(*servicename); +- if (*protocol) free(*protocol); +- return -1; +-} +- + static void + destroy_client(struct clnt_info *clp) + { ++ printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd); + if (clp->krb5_poll_index != -1) + memset(&pollarray[clp->krb5_poll_index], 0, + sizeof(struct pollfd)); +@@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp) + if (clp->spkm3_fd != -1) close(clp->spkm3_fd); + if (clp->dirname) free(clp->dirname); + if (clp->servicename) free(clp->servicename); +- if (clp->servername) free(clp->servername); +- if (clp->protocol) free(clp->protocol); + free(clp); + } - if (!fg) -+ mydaemon(0, 0); -+ -+ signal(SIGINT, sig_die); -+ signal(SIGTERM, sig_die); -+ signal(SIGHUP, sig_hup); -+ -+ if (!fg) - release_parent(); +@@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info + { + char kname[32]; + char sname[32]; +- char info_file_name[32]; -- gssd_run(); -+ gssd_init_unique(GSSD_SVC); -+ -+ svcgssd_run(); - printerr(0, "gssd_run returned!\n"); - abort(); + if (clp->krb5_fd == -1) { + snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname); +@@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info + } + if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1)) + return -1; +- snprintf(info_file_name, sizeof(info_file_name), "%s/info", +- clp->dirname); +- if ((clp->servicename == NULL) && +- read_service_info(info_file_name, &clp->servicename, +- &clp->servername, &clp->prog, &clp->vers, +- &clp->protocol)) +- return -1; + return 0; } ---- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-10-30 17:23:21.000000000 -0700 -@@ -35,7 +35,6 @@ - - #include - #include --#include - #include - #include -@@ -44,25 +43,28 @@ - #include - #include - #include --#include -+#include +@@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp) + } + pollarray[clp->krb5_poll_index].fd = clp->krb5_fd; + pollarray[clp->krb5_poll_index].events |= POLLIN; ++ printerr(2, "monitoring krb5 channel under %s\n", ++ clp->dirname); + } - #include "svcgssd.h" - #include "gss_util.h" - #include "err_util.h" - #include "context.h" - #include "cacheio.h" -+#include "lsupport.h" + if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) { +@@ -386,54 +302,87 @@ find_client(char *dirname) + int + update_client_list(void) + { +- struct dirent **namelist; ++ char lustre_dir[PATH_MAX]; ++ struct dirent lustre_dirent = { .d_name = "lustre" }; ++ struct dirent *namelist[1]; ++ struct stat statbuf; + int i, j; - extern char * mech2file(gss_OID mech); --#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel" --#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel" -+#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel" -+#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.init/channel" +- if (chdir(pipefs_nfsdir) < 0) { ++ if (chdir(pipefs_dir) < 0) { + printerr(0, "ERROR: can't chdir to %s: %s\n", +- pipefs_nfsdir, strerror(errno)); ++ pipefs_dir, strerror(errno)); + return -1; + } - #define TOKEN_BUF_SIZE 8192 +- j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort); +- if (j < 0) { +- printerr(0, "ERROR: can't scandir %s: %s\n", +- pipefs_nfsdir, strerror(errno)); +- return -1; ++ snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre"); ++ if (stat(lustre_dir, &statbuf) == 0) { ++ namelist[0] = &lustre_dirent; ++ j = 1; ++ printerr(2, "re-processing lustre directory\n"); ++ } else { ++ namelist[0] = NULL; ++ j = 0; ++ printerr(2, "lustre directory not exist\n"); + } ++ + update_old_clients(namelist, j); + for (i=0; i < j; i++) { +- if (i < FD_ALLOC_BLOCK +- && !strncmp(namelist[i]->d_name, "clnt", 4) +- && !find_client(namelist[i]->d_name)) ++ if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name)) + process_clnt_dir(namelist[i]->d_name); +- free(namelist[i]); + } - struct svc_cred { -- uid_t cr_uid; -- gid_t cr_gid; -- int cr_ngroups; -- gid_t cr_groups[NGROUPS]; -+ uint32_t cr_remote; -+ uint32_t cr_usr_root; -+ uint32_t cr_usr_mds; -+ uid_t cr_uid; -+ uid_t cr_mapped_uid; -+ uid_t cr_gid; - }; +- free(namelist); ++ chdir("/"); + return 0; + } ++/* Context creation response. */ ++struct lustre_gss_init_res { ++ gss_buffer_desc gr_ctx; /* context handle */ ++ u_int gr_major; /* major status */ ++ u_int gr_minor; /* minor status */ ++ u_int gr_win; /* sequence window */ ++ gss_buffer_desc gr_token; /* token */ ++}; ++ ++struct lustre_gss_data { ++ int lgd_established; ++ int lgd_lustre_svc; /* mds/oss */ ++ int lgd_uid; /* uid */ ++ char *lgd_uuid; /* client device uuid */ ++ gss_name_t lgd_name; /* service name */ ++ ++ gss_OID lgd_mech; /* mech OID */ ++ u_int lgd_req_flags; /* request flags */ ++ gss_cred_id_t lgd_cred; /* credential */ ++ gss_ctx_id_t lgd_ctx; /* session context */ ++ gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */ ++ uint32_t lgd_seq_win; /* sequence window */ ++ ++ int lgd_rpc_err; ++ int lgd_gss_err; ++}; ++ static int -@@ -70,10 +72,9 @@ - gss_OID mech, gss_buffer_desc *context_token) +-do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, +- gss_buffer_desc *context_token) ++do_downcall(int k5_fd, struct lgssd_upcall_data *updata, ++ struct lustre_gss_data *lgd, gss_buffer_desc *context_token) { - FILE *f; -- int i; - char *fname = NULL; + char *buf = NULL, *p = NULL, *end = NULL; + unsigned int timeout = 0; /* XXX decide on a reasonable value */ + unsigned int buf_size = 0; - printerr(1, "doing downcall\n"); +- buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) + +- sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length + + printerr(2, "doing downcall\n"); - if ((fname = mech2file(mech)) == NULL) - goto out_err; - f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w"); -@@ -86,11 +87,12 @@ - qword_printhex(f, out_handle->value, out_handle->length); - /* XXX are types OK for the rest of this? */ - qword_printint(f, 0x7fffffff); /*XXX need a better timeout */ -+ qword_printint(f, cred->cr_remote); -+ qword_printint(f, cred->cr_usr_root); -+ qword_printint(f, cred->cr_usr_mds); -+ qword_printint(f, cred->cr_mapped_uid); - qword_printint(f, cred->cr_uid); - qword_printint(f, cred->cr_gid); -- qword_printint(f, cred->cr_ngroups); -- for (i=0; i < cred->cr_ngroups; i++) -- qword_printint(f, cred->cr_groups[i]); - qword_print(f, fname); - qword_printhex(f, context_token->value, context_token->length); - qword_eol(f); -@@ -119,7 +121,7 @@ - /* XXXARG: */ - int g; - -- printerr(1, "sending null reply\n"); -+ printerr(2, "sending null reply\n"); ++ buf_size = sizeof(updata->seq) + sizeof(timeout) + ++ sizeof(lgd->lgd_seq_win) + ++ sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length + + sizeof(context_token->length) + context_token->length; + p = buf = malloc(buf_size); + end = buf + buf_size; - qword_addhex(&bp, &blen, in_handle->value, in_handle->length); - qword_addhex(&bp, &blen, in_token->value, in_token->length); -@@ -159,6 +161,7 @@ - #define rpcsec_gsserr_credproblem 13 - #define rpcsec_gsserr_ctxproblem 14 +- if (WRITE_BYTES(&p, end, uid)) goto out_err; ++ if (WRITE_BYTES(&p, end, updata->seq)) goto out_err; + /* Not setting any timeout for now: */ + if (WRITE_BYTES(&p, end, timeout)) goto out_err; +- if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err; +- if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err; ++ if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err; ++ if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err; + if (write_buffer(&p, end, context_token)) goto out_err; -+#if 0 - static void - add_supplementary_groups(char *secname, char *name, struct svc_cred *cred) - { -@@ -182,7 +185,9 @@ - } - } + if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; +@@ -441,12 +390,13 @@ do_downcall(int k5_fd, uid_t uid, struct + return 0; + out_err: + if (buf) free(buf); +- printerr(0, "Failed to write downcall!\n"); ++ printerr(0, "ERROR: Failed to write downcall!\n"); + return -1; } -+#endif -+#if 0 static int - get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred) +-do_error_downcall(int k5_fd, uid_t uid, int err) ++do_error_downcall(int k5_fd, struct lgssd_upcall_data *updata, ++ int rpc_err, int gss_err) { -@@ -248,7 +253,9 @@ - out: - return res; + char buf[1024]; + char *p = buf, *end = buf + 1024; +@@ -455,11 +405,12 @@ do_error_downcall(int k5_fd, uid_t uid, + + printerr(1, "doing error downcall\n"); + +- if (WRITE_BYTES(&p, end, uid)) goto out_err; ++ if (WRITE_BYTES(&p, end, updata->seq)) goto out_err; + if (WRITE_BYTES(&p, end, timeout)) goto out_err; + /* use seq_win = 0 to indicate an error: */ + if (WRITE_BYTES(&p, end, zero)) goto out_err; +- if (WRITE_BYTES(&p, end, err)) goto out_err; ++ if (WRITE_BYTES(&p, end, rpc_err)) goto out_err; ++ if (WRITE_BYTES(&p, end, gss_err)) goto out_err; + + if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; + return 0; +@@ -468,6 +419,7 @@ out_err: + return -1; } -+#endif +#if 0 - void - print_hexl(int pri, unsigned char *cp, int length) - { -@@ -285,12 +292,113 @@ - printerr(pri,"\n"); - } + /* + * Create an RPC connection and establish an authenticated + * gss context with a server. +@@ -659,7 +611,287 @@ int create_auth_rpc_client(struct clnt_i + + goto out; } +#endif + -+static int -+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, -+ lnet_nid_t nid, uint32_t lustre_svc) ++static ++int do_negotiation(struct lustre_gss_data *lgd, ++ gss_buffer_desc *gss_token, ++ struct lustre_gss_init_res *gr, ++ int timeout) ++{ ++ char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel"; ++ struct lgssd_ioctl_param param; ++ struct passwd *pw; ++ int fd, ret; ++ char outbuf[8192]; ++ unsigned int *p; ++ int res; ++ ++ pw = getpwuid(lgd->lgd_uid); ++ if (!pw) { ++ printerr(0, "no uid %u in local user database\n", ++ lgd->lgd_uid); ++ return -1; ++ } ++ ++ param.version = GSSD_INTERFACE_VERSION; ++ param.uuid = lgd->lgd_uuid; ++ param.lustre_svc = lgd->lgd_lustre_svc; ++ param.uid = lgd->lgd_uid; ++ param.gid = pw->pw_gid; ++ param.send_token_size = gss_token->length; ++ param.send_token = (char *) gss_token->value; ++ param.reply_buf_size = sizeof(outbuf); ++ param.reply_buf = outbuf; ++ ++ fd = open(file, O_RDWR); ++ if (fd < 0) { ++ printerr(0, "can't open file %s\n", file); ++ return -1; ++ } ++ ++ ret = write(fd, ¶m, sizeof(param)); ++ ++ if (ret != sizeof(param)) { ++ printerr(0, "lustre ioctl err: %d\n", strerror(errno)); ++ close(fd); ++ return -1; ++ } ++ if (param.status) { ++ close(fd); ++ printerr(0, "status: %d (%s)\n", ++ param.status, strerror((int)param.status)); ++ if (param.status == -ETIMEDOUT) { ++ /* kernel return -ETIMEDOUT means the rpc timedout, ++ * we should notify the caller to reinitiate the ++ * gss negotiation, by return -ERESTART ++ */ ++ lgd->lgd_rpc_err = -ERESTART; ++ lgd->lgd_gss_err = 0; ++ } else { ++ lgd->lgd_rpc_err = param.status; ++ lgd->lgd_gss_err = 0; ++ } ++ return -1; ++ } ++ p = (unsigned int *)outbuf; ++ res = *p++; ++ gr->gr_major = *p++; ++ gr->gr_minor = *p++; ++ gr->gr_win = *p++; ++ ++ gr->gr_ctx.length = *p++; ++ gr->gr_ctx.value = malloc(gr->gr_ctx.length); ++ memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length); ++ p += (((gr->gr_ctx.length + 3) & ~3) / 4); ++ ++ gr->gr_token.length = *p++; ++ gr->gr_token.value = malloc(gr->gr_token.length); ++ memcpy(gr->gr_token.value, p, gr->gr_token.length); ++ p += (((gr->gr_token.length + 3) & ~3) / 4); ++ ++ printerr(2, "do_negotiation: receive handle len %d, token len %d\n", ++ gr->gr_ctx.length, gr->gr_token.length); ++ close(fd); ++ return 0; ++} ++ ++static ++int gssd_refresh_lgd(struct lustre_gss_data *lgd) ++{ ++ struct lustre_gss_init_res gr; ++ gss_buffer_desc *recv_tokenp, send_token; ++ OM_uint32 maj_stat, min_stat, call_stat, ret_flags; ++ ++ /* GSS context establishment loop. */ ++ memset(&gr, 0, sizeof(gr)); ++ recv_tokenp = GSS_C_NO_BUFFER; ++ ++ for (;;) { ++ /* print the token we just received */ ++ if (recv_tokenp != GSS_C_NO_BUFFER) { ++ printerr(3, "The received token length %d\n", ++ recv_tokenp->length); ++ print_hexl(3, recv_tokenp->value, recv_tokenp->length); ++ } ++ ++ maj_stat = gss_init_sec_context(&min_stat, ++ lgd->lgd_cred, ++ &lgd->lgd_ctx, ++ lgd->lgd_name, ++ lgd->lgd_mech, ++ lgd->lgd_req_flags, ++ 0, /* time req */ ++ NULL, /* channel */ ++ recv_tokenp, ++ NULL, /* used mech */ ++ &send_token, ++ &ret_flags, ++ NULL); /* time rec */ ++ ++ if (recv_tokenp != GSS_C_NO_BUFFER) { ++ gss_release_buffer(&min_stat, &gr.gr_token); ++ recv_tokenp = GSS_C_NO_BUFFER; ++ } ++ if (maj_stat != GSS_S_COMPLETE && ++ maj_stat != GSS_S_CONTINUE_NEEDED) { ++ pgsserr("gss_init_sec_context", maj_stat, min_stat, ++ lgd->lgd_mech); ++ break; ++ } ++ if (send_token.length != 0) { ++ memset(&gr, 0, sizeof(gr)); ++ ++ /* print the token we are about to send */ ++ printerr(3, "token being sent length %d\n", ++ send_token.length); ++ print_hexl(3, send_token.value, send_token.length); ++ ++ call_stat = do_negotiation(lgd, &send_token, &gr, 0); ++ gss_release_buffer(&min_stat, &send_token); ++ ++ if (call_stat != 0 || ++ (gr.gr_major != GSS_S_COMPLETE && ++ gr.gr_major != GSS_S_CONTINUE_NEEDED)) { ++ printerr(0, "call stat %d, major stat 0x%x\n", ++ (int)call_stat, gr.gr_major); ++ return -1; ++ } ++ ++ if (gr.gr_ctx.length != 0) { ++ if (lgd->lgd_rmt_ctx.value) ++ gss_release_buffer(&min_stat, ++ &lgd->lgd_rmt_ctx); ++ lgd->lgd_rmt_ctx = gr.gr_ctx; ++ } ++ if (gr.gr_token.length != 0) { ++ if (maj_stat != GSS_S_CONTINUE_NEEDED) ++ break; ++ recv_tokenp = &gr.gr_token; ++ } ++ } ++ ++ /* GSS_S_COMPLETE => check gss header verifier, ++ * usually checked in gss_validate ++ */ ++ if (maj_stat == GSS_S_COMPLETE) { ++ lgd->lgd_established = 1; ++ lgd->lgd_seq_win = gr.gr_win; ++ break; ++ } ++ } ++ /* End context negotiation loop. */ ++ if (!lgd->lgd_established) { ++ if (gr.gr_token.length != 0) ++ gss_release_buffer(&min_stat, &gr.gr_token); ++ ++ printerr(0, "context negotiation failed\n"); ++ return -1; ++ } ++ ++ printerr(2, "successfully refreshed lgd\n"); ++ return 0; ++} + ++static ++int gssd_create_lgd(struct clnt_info *clp, ++ struct lustre_gss_data *lgd, ++ struct lgssd_upcall_data *updata, ++ int authtype) +{ -+ u_int32_t maj_stat, min_stat; -+ gss_buffer_desc name; -+ char *sname, *realm, *slash; -+ int res = -1; -+ gss_OID name_type = GSS_C_NO_OID; -+ struct passwd *pw; ++ gss_buffer_desc sname; ++ OM_uint32 maj_stat, min_stat; ++ int retval = -1; + -+ memset(cred, 0, sizeof(*cred)); ++ lgd->lgd_established = 0; ++ lgd->lgd_lustre_svc = updata->svc; ++ lgd->lgd_uid = updata->uid; ++ lgd->lgd_uuid = updata->obd; + -+ maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr("get_ids: gss_display_name", -+ maj_stat, min_stat, mech); ++ switch (authtype) { ++ case AUTHTYPE_KRB5: ++ lgd->lgd_mech = (gss_OID) &krb5oid; ++ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; ++ break; ++ case AUTHTYPE_SPKM3: ++ lgd->lgd_mech = (gss_OID) &spkm3oid; ++ /* XXX sec.req_flags = GSS_C_ANON_FLAG; ++ * Need a way to switch.... ++ */ ++ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; ++ break; ++ default: ++ printerr(0, "Invalid authentication type (%d)\n", authtype); + return -1; + } -+ if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */ -+ !(sname = calloc(name.length + 1, 1))) { -+ printerr(0, "WARNING: get_ids: error allocating %d bytes " -+ "for sname\n", name.length + 1); -+ gss_release_buffer(&min_stat, &name); -+ return -1; ++ ++ lgd->lgd_cred = GSS_C_NO_CREDENTIAL; ++ lgd->lgd_ctx = GSS_C_NO_CONTEXT; ++ lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER; ++ lgd->lgd_seq_win = 0; ++ ++ sname.value = clp->servicename; ++ sname.length = strlen(clp->servicename); ++ ++ maj_stat = gss_import_name(&min_stat, &sname, ++ (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, ++ &lgd->lgd_name); ++ if (maj_stat != GSS_S_COMPLETE) { ++ pgsserr(0, maj_stat, min_stat, lgd->lgd_mech); ++ goto out_fail; + } -+ memcpy(sname, name.value, name.length); -+ printerr(1, "authenticated %s from %016llx\n", sname, nid); -+ gss_release_buffer(&min_stat, &name); + -+ if (lustre_svc == LUSTRE_GSS_SVC_MDS) -+ lookup_mapping(sname, nid, &cred->cr_mapped_uid); -+ else -+ cred->cr_mapped_uid = -1; ++ retval = gssd_refresh_lgd(lgd); + -+ realm = strchr(sname, '@'); -+ if (!realm) { -+ printerr(0, "WARNNING: principal %s contains no realm name\n", -+ sname); -+ cred->cr_remote = (mds_local_realm != NULL); -+ } else { -+ *realm++ = '\0'; -+ if (!mds_local_realm) -+ cred->cr_remote = 1; -+ else -+ cred->cr_remote = -+ (strcasecmp(mds_local_realm, realm) != 0); -+ } ++ if (lgd->lgd_name != GSS_C_NO_NAME) ++ gss_release_name(&min_stat, &lgd->lgd_name); + -+ if (cred->cr_remote) { -+ if (cred->cr_mapped_uid != -1) -+ res = 0; -+ else -+ printerr(0, "principal %s is remote without mapping\n", -+ sname); -+ goto out_free; -+ } ++ if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL) ++ gss_release_cred(&min_stat, &lgd->lgd_cred); + -+ slash = strchr(sname, '/'); -+ if (slash) -+ *slash = '\0'; ++ out_fail: ++ return retval; ++} + -+ if (!(pw = getpwnam(sname))) { -+ /* If client use machine credential, we map it to root, which -+ * will subject to further mapping by root-squash in kernel. -+ * -+ * MDS service keytab is treated as special user, also mapped -+ * to root. OSS service keytab can't be used as a user. -+ */ -+ if (!strcmp(sname, LUSTRE_ROOT_NAME)) { -+ printerr(2, "lustre_root principal, resolve to uid 0\n"); -+ cred->cr_uid = 0; -+ cred->cr_usr_root = 1; -+ } else if (!strcmp(sname, GSSD_SERVICE_MDS)) { -+ printerr(2, "mds service principal, resolve to uid 0\n"); -+ cred->cr_uid = 0; -+ cred->cr_usr_mds = 1; -+ } else { -+ cred->cr_uid = -1; -+ if (cred->cr_mapped_uid == -1) { -+ printerr(0, "invalid user %s\n", sname); -+ goto out_free; -+ } -+ printerr(2, "user %s mapped to %u\n", -+ sname, cred->cr_mapped_uid); -+ } -+ } else { -+ cred->cr_uid = pw->pw_uid; -+ printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid); -+ } ++static ++void gssd_free_lgd(struct lustre_gss_data *lgd) ++{ ++ gss_buffer_t token = GSS_C_NO_BUFFER; ++ OM_uint32 maj_stat, min_stat; + -+ res = 0; -+out_free: -+ free(sname); -+ return res; ++ if (lgd->lgd_ctx == GSS_C_NO_CONTEXT) ++ return; ++ ++ maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token); +} + -+typedef struct gss_union_ctx_id_t { -+ gss_OID mech_type; -+ gss_ctx_id_t internal_ctx_id; -+} gss_union_ctx_id_desc, *gss_union_ctx_id_t; ++static ++int construct_service_name(struct clnt_info *clp, ++ struct lgssd_upcall_data *ud) ++{ ++ const int buflen = 256; ++ char name[buflen]; ++ ++ if (clp->servicename) { ++ free(clp->servicename); ++ clp->servicename = NULL; ++ } ++ ++ if (lnet_nid2hostname(ud->nid, name, buflen)) ++ return -1; ++ ++ clp->servicename = malloc(32 + strlen(name)); ++ if (!clp->servicename) { ++ printerr(0, "can't alloc memory\n"); ++ return -1; ++ } ++ sprintf(clp->servicename, "%s@%s", ++ ud->svc == LUSTRE_GSS_SVC_MDS ? ++ GSSD_SERVICE_MDS : GSSD_SERVICE_OSS, ++ name); ++ printerr(2, "constructed servicename: %s\n", clp->servicename); ++ return 0; ++} + /* + * this code uses the userland rpcsec gss library to create a krb5 +@@ -668,27 +900,63 @@ int create_auth_rpc_client(struct clnt_i void - handle_nullreq(FILE *f) { -- /* XXX initialize to a random integer to reduce chances of unnecessary -- * invalidation of existing ctx's on restarting svcgssd. */ -- static u_int32_t handle_seq = 0; -+ uint64_t handle_seq; - char in_tok_buf[TOKEN_BUF_SIZE]; - char in_handle_buf[15]; - char out_handle_buf[15]; -@@ -302,10 +410,13 @@ - ignore_out_tok = {.value = NULL}, - /* XXX isn't there a define for this?: */ - null_token = {.value = NULL}; -+ uint32_t lustre_svc; -+ lnet_nid_t nid; - u_int32_t ret_flags; - gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; - gss_name_t client_name; - gss_OID mech = GSS_C_NO_OID; -+ gss_cred_id_t svc_cred; - u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0; - u_int32_t ignore_min_stat; - struct svc_cred cred; -@@ -313,7 +424,7 @@ - static int lbuflen = 0; - static char *cp; - -- printerr(1, "handling null request\n"); -+ printerr(2, "handling null request\n"); - - if (readline(fileno(f), &lbuf, &lbuflen) != 1) { - printerr(0, "WARNING: handle_nullreq: " -@@ -323,15 +434,21 @@ - - cp = lbuf; - -+ qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc)); -+ qword_get(&cp, (char *) &nid, sizeof(nid)); -+ qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq)); -+ printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n", -+ lustre_svc, nid, handle_seq); -+ - in_handle.length = (size_t) qword_get(&cp, in_handle.value, - sizeof(in_handle_buf)); -- printerr(2, "in_handle: \n"); -- print_hexl(2, in_handle.value, in_handle.length); -+ printerr(3, "in_handle: \n"); -+ print_hexl(3, in_handle.value, in_handle.length); + handle_krb5_upcall(struct clnt_info *clp) + { +- uid_t uid; +- CLIENT *rpc_clnt = NULL; +- AUTH *auth = NULL; +- struct authgss_private_data pd; +- gss_buffer_desc token; ++ gss_buffer_desc token = { 0, NULL }; ++ struct lgssd_upcall_data updata; ++ struct lustre_gss_data lgd; + char **credlist = NULL; + char **ccname; ++ int read_rc; - in_tok.length = (size_t) qword_get(&cp, in_tok.value, - sizeof(in_tok_buf)); -- printerr(2, "in_tok: \n"); -- print_hexl(2, in_tok.value, in_tok.length); -+ printerr(3, "in_tok: \n"); -+ print_hexl(3, in_tok.value, in_tok.length); +- printerr(1, "handling krb5 upcall\n"); ++ printerr(2, "handling krb5 upcall\n"); - if (in_tok.length < 0) { - printerr(0, "WARNING: handle_nullreq: " -@@ -351,7 +468,13 @@ - memcpy(&ctx, in_handle.value, in_handle.length); +- token.length = 0; +- token.value = NULL; +- memset(&pd, 0, sizeof(struct authgss_private_data)); ++ memset(&lgd, 0, sizeof(lgd)); ++ lgd.lgd_rpc_err = -EPERM; /* default error code */ + +- if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) { +- printerr(0, "WARNING: failed reading uid from krb5 " ++ read_rc = read(clp->krb5_fd, &updata, sizeof(updata)); ++ if (read_rc < 0) { ++ printerr(0, "WARNING: failed reading from krb5 " + "upcall pipe: %s\n", strerror(errno)); + goto out; ++ } else if (read_rc != sizeof(updata)) { ++ printerr(0, "upcall data mismatch: length %d, expect %d\n", ++ read_rc, sizeof(updata)); ++ ++ if (read_rc >= 4) ++ goto out_return_error; ++ else ++ goto out; } -- maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds, -+ svc_cred = gssd_select_svc_cred(lustre_svc); -+ if (!svc_cred) { -+ printerr(0, "no service credential for svc %u\n", lustre_svc); -+ goto out_err; +- if (uid == 0) { ++ printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, " ++ "pag %llx, obd %s\n", updata.seq, updata.uid, updata.svc, ++ updata.nid, updata.pag, updata.obd); ++ ++ /* XXX in kernel pag is defined as "unsigned long", which might ++ * not keep original signed value after converted to u64. ++ */ ++ if (updata.pag != updata.uid && ++ ((updata.pag == 0xffffffffffffffffULL) || ++ (updata.pag == 0xffffffff))) { ++ printerr(0, "uid %u: pag %llx not allowed\n", ++ updata.uid, updata.pag); ++ lgd.lgd_rpc_err = -EPROTO; ++ goto out_return_error; + } + -+ maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred, - &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name, - &mech, &out_tok, &ret_flags, NULL, NULL); ++ if (updata.svc != LUSTRE_GSS_SVC_MDS && ++ updata.svc != LUSTRE_GSS_SVC_OSS) { ++ printerr(0, "invalid svc %d\n", updata.svc); ++ lgd.lgd_rpc_err = -EPROTO; ++ goto out_return_error; ++ } ++ updata.obd[sizeof(updata.obd)-1] = '\0'; ++ ++ if (construct_service_name(clp, &updata)) { ++ printerr(0, "failed to construct service name\n"); ++ goto out_return_error; ++ } ++ ++ if (updata.uid == 0) { + int success = 0; -@@ -369,7 +492,8 @@ - maj_stat, min_stat, mech); - goto out_err; + /* +@@ -696,75 +964,66 @@ handle_krb5_upcall(struct clnt_info *clp + * of them until one works or we've tried them all + */ + if (gssd_get_krb5_machine_cred_list(&credlist)) { +- printerr(0, "WARNING: Failed to obtain machine " +- "credentials for connection to " +- "server %s\n", clp->servername); +- goto out_return_error; ++ printerr(0, "ERROR: Failed to obtain machine " ++ "credentials for %s\n", clp->servicename); ++ goto out_return_error; + } + for (ccname = credlist; ccname && *ccname; ccname++) { + gssd_setup_krb5_machine_gss_ccache(*ccname); +- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, +- AUTHTYPE_KRB5)) == 0) { ++ if ((gssd_create_lgd(clp, &lgd, &updata, ++ AUTHTYPE_KRB5)) == 0) { + /* Success! */ + success++; + break; + } + printerr(2, "WARNING: Failed to create krb5 context " + "for user with uid %d with credentials " +- "cache %s for server %s\n", +- uid, *ccname, clp->servername); ++ "cache %s for service %s\n", ++ updata.uid, *ccname, clp->servicename); + } + gssd_free_krb5_machine_cred_list(credlist); + if (!success) { +- printerr(0, "WARNING: Failed to create krb5 context " ++ printerr(0, "ERROR: Failed to create krb5 context " + "for user with uid %d with any " +- "credentials cache for server %s\n", +- uid, clp->servername); ++ "credentials cache for service %s\n", ++ updata.uid, clp->servicename); + goto out_return_error; + } } -- if (get_ids(client_name, mech, &cred)) { -+ -+ if (get_ids(client_name, mech, &cred, nid, lustre_svc)) { - /* get_ids() prints error msg */ - maj_stat = GSS_S_BAD_NAME; /* XXX ? */ - gss_release_name(&ignore_min_stat, &client_name); -@@ -377,10 +501,8 @@ + else { + /* Tell krb5 gss which credentials cache to use */ +- gssd_setup_krb5_user_gss_ccache(uid, clp->servername); ++ gssd_setup_krb5_user_gss_ccache(updata.pag, updata.uid, ++ clp->servicename); + +- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, +- AUTHTYPE_KRB5)) != 0) { ++ if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) { + printerr(0, "WARNING: Failed to create krb5 context " +- "for user with uid %d for server %s\n", +- uid, clp->servername); ++ "for user with uid %d for service %s\n", ++ updata.uid, clp->servicename); + goto out_return_error; + } } - gss_release_name(&ignore_min_stat, &client_name); +- if (!authgss_get_private_data(auth, &pd)) { +- printerr(0, "WARNING: Failed to obtain authentication " +- "data for user with uid %d for server %s\n", +- uid, clp->servername); +- goto out_return_error; +- } - - /* Context complete. Pass handle_seq in out_handle to use - * for context lookup in the kernel. */ -- handle_seq++; - out_handle.length = sizeof(handle_seq); - memcpy(out_handle.value, &handle_seq, sizeof(handle_seq)); +- if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) { ++ if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) { + printerr(0, "WARNING: Failed to serialize krb5 context for " +- "user with uid %d for server %s\n", +- uid, clp->servername); ++ "user with uid %d for service %s\n", ++ updata.uid, clp->servicename); + goto out_return_error; + } -@@ -404,7 +526,6 @@ - free(ctx_token.value); - if (out_tok.value != NULL) - gss_release_buffer(&ignore_min_stat, &out_tok); -- printerr(1, "finished handling null request\n"); +- do_downcall(clp->krb5_fd, uid, &pd, &token); ++ printerr(1, "refreshed: %u@%s for %s\n", ++ updata.uid, updata.obd, clp->servicename); ++ do_downcall(clp->krb5_fd, &updata, &lgd, &token); + + out: + if (token.value) + free(token.value); +- if (pd.pd_ctx_hndl.length != 0) +- authgss_free_private_data(&pd); +- if (auth) +- AUTH_DESTROY(auth); +- if (rpc_clnt) +- clnt_destroy(rpc_clnt); ++ ++ gssd_free_lgd(&lgd); return; - out_err: ---- nfs-utils-1.0.10/utils/gssd/gss_util.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/gss_util.c 2006-10-30 16:40:47.000000000 -0700 + out_return_error: +- do_error_downcall(clp->krb5_fd, uid, -1); ++ do_error_downcall(clp->krb5_fd, &updata, ++ lgd.lgd_rpc_err, lgd.lgd_gss_err); + goto out; + } + +@@ -775,6 +1034,7 @@ out_return_error: + void + handle_spkm3_upcall(struct clnt_info *clp) + { ++#if 0 + uid_t uid; + CLIENT *rpc_clnt = NULL; + AUTH *auth = NULL; +@@ -826,4 +1086,5 @@ out: + out_return_error: + do_error_downcall(clp->spkm3_fd, uid, -1); + goto out; ++#endif + } +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_util.c nfs-utils-1.0.10/utils/gssd/gss_util.c +--- nfs-utils-1.0.10.orig/utils/gssd/gss_util.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/gss_util.c 2006-11-15 21:44:43.000000000 -0700 @@ -87,9 +87,16 @@ #ifdef HAVE_COM_ERR_H #include @@ -1297,7 +1373,7 @@ gss_OID g_mechOid = GSS_C_NULL_OID;; -@@ -183,15 +190,51 @@ +@@ -183,15 +190,51 @@ pgsserr(char *msg, u_int32_t maj_stat, u display_status_2(msg, maj_stat, min_stat, mech); } @@ -1351,7 +1427,7 @@ name.value = (void *)server_name; name.length = strlen(server_name); -@@ -201,12 +244,20 @@ +@@ -201,12 +244,20 @@ gssd_acquire_cred(char *server_name) if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid); @@ -1374,7 +1450,7 @@ if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid); -@@ -218,11 +269,65 @@ +@@ -218,11 +269,65 @@ gssd_acquire_cred(char *server_name) ignore_maj_stat = gss_release_buffer(&ignore_min_stat, &pbuf); } @@ -1442,78 +1518,25 @@ } int gssd_check_mechs(void) ---- nfs-utils-1.0.10/utils/gssd/gss_util.h.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/gss_util.h 2006-10-30 16:40:47.000000000 -0700 +diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_util.h nfs-utils-1.0.10/utils/gssd/gss_util.h +--- nfs-utils-1.0.10.orig/utils/gssd/gss_util.h 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/gss_util.h 2006-11-15 21:44:43.000000000 -0700 @@ -32,12 +32,10 @@ - #define _GSS_UTIL_H_ - - #include --#include - #include "write_bytes.h" - - extern gss_cred_id_t gssd_creds; - --int gssd_acquire_cred(char *server_name); - void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, - const gss_OID mech); - int gssd_check_mechs(void); ---- nfs-utils-1.0.10/utils/gssd/krb5_util.h.lustre 2006-10-30 16:40:17.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/krb5_util.h 2006-10-30 16:40:47.000000000 -0700 -@@ -10,13 +10,15 @@ - struct gssd_k5_kt_princ { - struct gssd_k5_kt_princ *next; - krb5_principal princ; -+ unsigned int fl_root:1, -+ fl_mds:1; - char *ccname; - char *realm; - krb5_timestamp endtime; - }; - - --void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername); -+void gssd_setup_krb5_user_gss_ccache(uint64_t pag, uid_t uid, char *servername); - int gssd_get_krb5_machine_cred_list(char ***list); - int gssd_refresh_krb5_machine_creds(void); - void gssd_free_krb5_machine_cred_list(char **list); -@@ -25,8 +27,32 @@ - void gssd_obtain_kernel_krb5_info(void); - - --#ifdef HAVE_SET_ALLOWABLE_ENCTYPES --int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid); --#endif -+#endif /* KRB5_UTIL_H */ -+#ifndef KRB5_UTIL_H -+#define KRB5_UTIL_H -+ -+#include -+ -+/* -+ * List of principals from our keytab that we -+ * may try to get credentials for -+ */ -+struct gssd_k5_kt_princ { -+ struct gssd_k5_kt_princ *next; -+ krb5_principal princ; -+ char *ccname; -+ char *realm; -+ krb5_timestamp endtime; -+}; -+ -+ -+void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername); -+int gssd_get_krb5_machine_cred_list(char ***list); -+int gssd_refresh_krb5_machine_creds(void); -+void gssd_free_krb5_machine_cred_list(char **list); -+void gssd_setup_krb5_machine_gss_ccache(char *servername); -+void gssd_destroy_krb5_machine_creds(void); -+void gssd_obtain_kernel_krb5_info(void); -+ + #define _GSS_UTIL_H_ - #endif /* KRB5_UTIL_H */ ---- nfs-utils-1.0.10/utils/gssd/krb5_util.c.lustre 2006-10-30 16:40:17.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/krb5_util.c 2006-10-30 16:40:47.000000000 -0700 + #include +-#include + #include "write_bytes.h" + + extern gss_cred_id_t gssd_creds; + +-int gssd_acquire_cred(char *server_name); + void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, + const gss_OID mech); + int gssd_check_mechs(void); +diff -rup nfs-utils-1.0.10.orig/utils/gssd/krb5_util.c nfs-utils-1.0.10/utils/gssd/krb5_util.c +--- nfs-utils-1.0.10.orig/utils/gssd/krb5_util.c 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/krb5_util.c 2006-11-15 21:44:43.000000000 -0700 @@ -99,12 +99,14 @@ #include #include @@ -1537,7 +1560,7 @@ #include "gssd.h" #include "err_util.h" -@@ -129,6 +130,12 @@ +@@ -129,6 +130,12 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin int num_krb5_enctypes = 0; krb5_enctype *krb5_enctypes = NULL; @@ -1550,7 +1573,7 @@ /*==========================*/ /*=== Internal routines ===*/ /*==========================*/ -@@ -137,11 +144,55 @@ +@@ -137,11 +144,55 @@ static int select_krb5_ccache(const stru static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d); static int gssd_get_single_krb5_cred(krb5_context context, krb5_keytab kt, struct gssd_k5_kt_princ *ple); @@ -1607,7 +1630,7 @@ * Called from the scandir function to weed out potential krb5 * credentials cache files * -@@ -292,7 +343,7 @@ +@@ -294,7 +345,7 @@ gssd_get_single_krb5_cred(krb5_context c memset(&my_creds, 0, sizeof(my_creds)); @@ -1616,7 +1639,7 @@ printerr(2, "INFO: Credentials in CC '%s' are good until %d\n", ple->ccname, ple->endtime); code = 0; -@@ -323,11 +374,7 @@ +@@ -325,11 +376,7 @@ gssd_get_single_krb5_cred(krb5_context c "principal '%s' from keytab '%s'\n", error_message(code), pname ? pname : "", kt_name); @@ -1629,7 +1652,7 @@ goto out; } -@@ -371,15 +418,7 @@ +@@ -378,15 +425,7 @@ gssd_get_single_krb5_cred(krb5_context c return (code); } @@ -1646,7 +1669,7 @@ { struct gssd_k5_kt_princ *ple; #ifdef HAVE_KRB5 -@@ -389,18 +428,76 @@ +@@ -396,18 +435,76 @@ gssd_have_realm_ple(void *r) #endif for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) { @@ -1731,7 +1754,7 @@ /* * Process the given keytab file and create a list of principals we * might use to perform mount operations. -@@ -444,82 +541,106 @@ +@@ -451,82 +548,106 @@ gssd_process_krb5_keytab(krb5_context co } printerr(2, "Processing keytab entry for principal '%s'\n", pname); @@ -1907,7 +1930,7 @@ } if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) { -@@ -627,14 +748,21 @@ +@@ -634,14 +755,21 @@ parse_enctypes(char *enctypes) * void */ void @@ -1932,7 +1955,7 @@ if (gssd_find_existing_krb5_ccache(uid, &d)) { snprintf(buf, sizeof(buf), "FILE:%s/%s", ccachedir, d->d_name); -@@ -645,6 +773,7 @@ +@@ -652,6 +780,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid); printerr(2, "using %s as credentials cache for client with " "uid %u for server %s\n", buf, uid, servername); @@ -1940,7 +1963,7 @@ gssd_set_krb5_ccache_name(buf); } -@@ -695,7 +824,18 @@ +@@ -702,7 +831,18 @@ gssd_refresh_krb5_machine_creds(void) goto out; } @@ -1960,7 +1983,7 @@ if ((code = krb5_kt_resolve(context, keytabfile, &kt))) { printerr(0, "ERROR: %s while resolving keytab '%s'\n", -@@ -710,12 +850,12 @@ +@@ -717,12 +857,12 @@ gssd_refresh_krb5_machine_creds(void) if (gssd_k5_kt_princ_list == NULL) { printerr(0, "ERROR: No usable keytab entries found in " "keytab '%s'\n", keytabfile); @@ -1976,329 +1999,83 @@ + GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME, + keytabfile); } - } - -@@ -865,6 +1005,7 @@ - krb5_free_context(context); - } - -+#if 0 - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - /* - * this routine obtains a credentials handle via gss_acquire_cred() -@@ -920,6 +1061,7 @@ - return 0; - } - #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ -+#endif - - /* - * Obtain supported enctypes from kernel. ---- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c 2006-10-30 16:40:47.000000000 -0700 -@@ -47,6 +47,7 @@ - #include "gssd.h" - #include "write_bytes.h" - -+#if 0 - char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR; - - static void -@@ -102,3 +103,4 @@ - } - exit(0); - } -+#endif ---- nfs-utils-1.0.10/utils/gssd/context.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/context.c 2006-10-30 16:40:47.000000000 -0700 -@@ -33,8 +33,6 @@ - #include - #include - #include --#include --#include - #include "gss_util.h" - #include "gss_oids.h" - #include "err_util.h" ---- nfs-utils-1.0.10/utils/gssd/lsupport.h.lustre 2006-10-30 16:40:47.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/lsupport.h 2006-10-30 16:40:47.000000000 -0700 -@@ -0,0 +1,89 @@ -+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- -+ * vim:expandtab:shiftwidth=8:tabstop=8: -+ */ -+ -+#ifndef __LIBCFS_H__ -+#define __LIBCFS_H__ -+ -+#include -+#include -+ -+#define GSSD_CLI (0) -+#define GSSD_SVC (1) -+ -+void gssd_init_unique(int type); -+void gssd_exit_unique(int type); -+ -+/* -+ * copied from lustre source -+ */ -+ -+#define LUSTRE_GSS_SVC_MDS 0 -+#define LUSTRE_GSS_SVC_OSS 1 -+ -+struct lgssd_upcall_data { -+ uint32_t seq; -+ uint32_t uid; -+ uint32_t gid; -+ uint32_t svc; -+ uint64_t nid; -+ uint64_t pag; -+ char obd[64]; -+}; -+ -+#define GSSD_INTERFACE_VERSION (1) -+ -+struct lgssd_ioctl_param { -+ int version; /* in */ -+ char *uuid; /* in */ -+ int lustre_svc; /* in */ -+ uid_t uid; /* in */ -+ gid_t gid; /* in */ -+ long send_token_size;/* in */ -+ char *send_token; /* in */ -+ long reply_buf_size; /* in */ -+ char *reply_buf; /* in */ -+ long status; /* out */ -+ long reply_length; /* out */ -+}; -+ -+#define GSSD_DEFAULT_GETHOSTNAME_EX "/etc/lustre/nid2hostname" -+#define MAPPING_DATABASE_FILE "/etc/lustre/idmap.conf" -+ -+typedef uint64_t lnet_nid_t; -+typedef uint32_t lnet_netid_t; -+ -+#define LNET_NID_ANY ((lnet_nid_t) -1) -+#define LNET_PID_ANY ((lnet_pid_t) -1) -+ -+enum { -+ /* Only add to these values (i.e. don't ever change or redefine them): -+ * network addresses depend on them... */ -+ QSWLND = 1, -+ SOCKLND = 2, -+ GMLND = 3, -+ PTLLND = 4, -+ O2IBLND = 5, -+ CIBLND = 6, -+ OPENIBLND = 7, -+ IIBLND = 8, -+ LOLND = 9, -+ RALND = 10, -+ VIBLND = 11, -+ LND_ENUM_END_MARKER -+}; -+ -+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen); -+int lookup_mapping(char *princ, uint64_t nid, uid_t *uid); -+lnet_nid_t libcfs_str2nid(char *str); -+ -+/* how an LNET NID encodes net:address */ -+#define LNET_NIDADDR(nid) ((uint32_t)((nid) & 0xffffffff)) -+#define LNET_NIDNET(nid) ((uint32_t)(((nid) >> 32)) & 0xffffffff) -+#define LNET_MKNID(net,addr) ((((uint64_t)(net))<<32)|((uint64_t)(addr))) -+/* how net encodes type:number */ -+#define LNET_NETNUM(net) ((net) & 0xffff) -+#define LNET_NETTYP(net) (((net) >> 16) & 0xffff) -+#define LNET_MKNET(typ,num) ((((uint32_t)(typ))<<16)|((uint32_t)(num))) -+ -+#endif /* __LIBCFS_H__ */ ---- nfs-utils-1.0.10/utils/gssd/err_util.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/err_util.c 2006-10-30 16:40:47.000000000 -0700 -@@ -32,6 +32,8 @@ - #include - #include - #include -+#include -+#include - #include "err_util.h" - - static int verbosity = 0; -@@ -91,3 +93,40 @@ - /* reset the buffer */ - memset(message_buf, 0, sizeof(message_buf)); - } -+ -+void print_hexl(int pri, unsigned char *cp, int length) -+{ -+ int i, j, jm; -+ unsigned char c; -+ -+ printerr(pri, "length %d\n",length); -+ printerr(pri, "\n"); -+ -+ for (i = 0; i < length; i += 0x10) { -+ printerr(pri, " %04x: ", (u_int)i); -+ jm = length - i; -+ jm = jm > 16 ? 16 : jm; -+ -+ for (j = 0; j < jm; j++) { -+ if ((j % 2) == 1) -+ printerr(pri,"%02x ", (u_int)cp[i+j]); -+ else -+ printerr(pri,"%02x", (u_int)cp[i+j]); -+ } -+ for (; j < 16; j++) { -+ if ((j % 2) == 1) -+ printerr(pri," "); -+ else -+ printerr(pri," "); -+ } -+ printerr(pri," "); -+ -+ for (j = 0; j < jm; j++) { -+ c = cp[i+j]; -+ c = isprint(c) ? c : '.'; -+ printerr(pri,"%c", c); -+ } -+ printerr(pri,"\n"); -+ } -+} -+ ---- nfs-utils-1.0.10/utils/gssd/context_spkm3.c.lustre 2006-10-30 16:40:17.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2006-10-30 16:40:47.000000000 -0700 -@@ -33,8 +33,6 @@ - #include - #include - #include --#include --#include - #include "gss_util.h" - #include "gss_oids.h" - #include "err_util.h" ---- nfs-utils-1.0.10/utils/gssd/gssd.c.lustre 2006-10-30 16:40:17.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/gssd.c 2006-10-30 16:40:47.000000000 -0700 -@@ -40,7 +40,6 @@ - - #include - #include --#include - - #include - #include -@@ -52,6 +51,7 @@ - #include "err_util.h" - #include "gss_util.h" - #include "krb5_util.h" -+#include "lsupport.h" - - char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR; - char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE; -@@ -77,7 +77,7 @@ - static void - usage(char *progname) - { -- fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", -+ fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", - progname); - exit(1); - } -@@ -87,7 +87,6 @@ - { - int fg = 0; - int verbosity = 0; -- int rpc_verbosity = 0; - int opt; - extern char *optarg; - char *progname; -@@ -97,15 +96,9 @@ - case 'f': - fg = 1; - break; -- case 'm': -- /* Accept but ignore this. Now the default. */ -- break; - case 'v': - verbosity++; - break; -- case 'r': -- rpc_verbosity++; -- break; - case 'p': - strncpy(pipefsdir, optarg, sizeof(pipefsdir)); - if (pipefsdir[sizeof(pipefsdir)-1] != '\0') -@@ -126,10 +119,6 @@ - break; - } - } -- strncat(pipefsdir + strlen(pipefsdir), "/" GSSD_SERVICE_NAME, -- sizeof(pipefsdir)-strlen(pipefsdir)); -- if (pipefsdir[sizeof(pipefsdir)-1] != '\0') -- errx(1, "pipefs path name too long"); - - if ((progname = strrchr(argv[0], '/'))) - progname++; -@@ -137,30 +126,34 @@ - progname = argv[0]; - - initerr(progname, verbosity, fg); --#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL -- authgss_set_debug_level(rpc_verbosity); --#else -- if (rpc_verbosity > 0) -- printerr(0, "Warning: rpcsec_gss library does not " -- "support setting debug level\n"); --#endif + } - if (gssd_check_mechs() != 0) - errx(1, "Problem with gssapi library"); +@@ -872,6 +1012,7 @@ gssd_destroy_krb5_machine_creds(void) + krb5_free_context(context); + } +#if 0 -+ /* Determine Kerberos information from the kernel */ -+ gssd_obtain_kernel_krb5_info(); + #ifdef HAVE_SET_ALLOWABLE_ENCTYPES + /* + * this routine obtains a credentials handle via gss_acquire_cred() +@@ -927,6 +1068,7 @@ limit_krb5_enctypes(struct rpc_gss_sec * + return 0; + } + #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ +#endif -+ - if (!fg && daemon(0, 0) < 0) - errx(1, "fork"); -+ /* This should be checked _after_ daemon(), because we need to own -+ * the undo-able semaphore by this process -+ */ -+ gssd_init_unique(GSSD_CLI); + /* + * Obtain supported enctypes from kernel. +diff -rup nfs-utils-1.0.10.orig/utils/gssd/krb5_util.h nfs-utils-1.0.10/utils/gssd/krb5_util.h +--- nfs-utils-1.0.10.orig/utils/gssd/krb5_util.h 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/krb5_util.h 2006-11-15 21:44:43.000000000 -0700 +@@ -10,13 +10,15 @@ + struct gssd_k5_kt_princ { + struct gssd_k5_kt_princ *next; + krb5_principal princ; ++ unsigned int fl_root:1, ++ fl_mds:1; + char *ccname; + char *realm; + krb5_timestamp endtime; + }; + + +-void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername); ++void gssd_setup_krb5_user_gss_ccache(uint64_t pag, uid_t uid, char *servername); + int gssd_get_krb5_machine_cred_list(char ***list); + int gssd_refresh_krb5_machine_creds(void); + void gssd_free_krb5_machine_cred_list(char **list); +@@ -25,8 +27,32 @@ void gssd_destroy_krb5_machine_creds(voi + void gssd_obtain_kernel_krb5_info(void); + + +-#ifdef HAVE_SET_ALLOWABLE_ENCTYPES +-int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid); +-#endif ++#endif /* KRB5_UTIL_H */ ++#ifndef KRB5_UTIL_H ++#define KRB5_UTIL_H + -+ /* Process keytab file and get machine credentials. This will modify -+ * disk status so do it after we are sure we are the only instance -+ */ -+ if (gssd_refresh_krb5_machine_creds()) -+ return -1; ++#include ++ ++/* ++ * List of principals from our keytab that we ++ * may try to get credentials for ++ */ ++struct gssd_k5_kt_princ { ++ struct gssd_k5_kt_princ *next; ++ krb5_principal princ; ++ char *ccname; ++ char *realm; ++ krb5_timestamp endtime; ++}; ++ ++ ++void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername); ++int gssd_get_krb5_machine_cred_list(char ***list); ++int gssd_refresh_krb5_machine_creds(void); ++void gssd_free_krb5_machine_cred_list(char **list); ++void gssd_setup_krb5_machine_gss_ccache(char *servername); ++void gssd_destroy_krb5_machine_creds(void); ++void gssd_obtain_kernel_krb5_info(void); + - signal(SIGINT, sig_die); - signal(SIGTERM, sig_die); - signal(SIGHUP, sig_hup); - -- /* Process keytab file and get machine credentials */ -- gssd_refresh_krb5_machine_creds(); -- /* Determine Kerberos information from the kernel */ -- gssd_obtain_kernel_krb5_info(); -- -- gssd_run(); -+ lgssd_run(); - printerr(0, "gssd_run returned!\n"); - abort(); - } ---- nfs-utils-1.0.10/utils/gssd/cacheio.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/cacheio.c 2006-10-30 16:40:47.000000000 -0700 -@@ -227,7 +227,8 @@ - return -1; - while (*bp == ' ') bp++; - *bpp = bp; -- *dest = '\0'; -+// why should we clear *dest??? -+// *dest = '\0'; - return len; - } ---- nfs-utils-1.0.10/utils/gssd/lsupport.c.lustre 2006-10-30 16:40:47.000000000 -0700 -+++ nfs-utils-1.0.10/utils/gssd/lsupport.c 2006-10-30 17:42:31.000000000 -0700 + #endif /* KRB5_UTIL_H */ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/lsupport.c nfs-utils-1.0.10/utils/gssd/lsupport.c +--- nfs-utils-1.0.10.orig/utils/gssd/lsupport.c 2006-11-15 21:41:25.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/lsupport.c 2006-11-15 21:44:43.000000000 -0700 @@ -0,0 +1,782 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: @@ -2944,155 +2721,494 @@ + if (*p == '\0') + return (uid_t) uid; + -+ return -1; -+} ++ return -1; ++} ++ ++static ++int read_mapping_db(void) ++{ ++ char princ[MAX_LINE_LEN]; ++ char nid_str[MAX_LINE_LEN]; ++ char dest[MAX_LINE_LEN]; ++ lnet_nid_t nid; ++ uid_t dest_uid; ++ FILE *f; ++ char *line, linebuf[MAX_LINE_LEN]; ++ ++ /* cleanup old mappings */ ++ cleanup_mapping(); ++ ++ f = fopen(MAPPING_DATABASE_FILE, "r"); ++ if (!f) { ++ printerr(0, "can't open mapping database: %s\n", ++ MAPPING_DATABASE_FILE); ++ return -1; ++ } ++ ++ while ((line = fgets(linebuf, MAX_LINE_LEN, f))) { ++ char *name; ++ ++ if (strlen(line) >= MAX_LINE_LEN) { ++ printerr(0, "invalid mapping db: line too long (%d)\n", ++ strlen(line)); ++ cleanup_mapping(); ++ fclose(f); ++ return -1; ++ } ++ if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) { ++ printerr(0, "mapping db: syntax error\n"); ++ cleanup_mapping(); ++ fclose(f); ++ return -1; ++ } ++ if (grow_mapping(mapping.nitems + 1)) { ++ printerr(0, "fail to grow mapping to %d\n", ++ mapping.nitems + 1); ++ fclose(f); ++ return -1; ++ } ++ if (!strcmp(princ, "*")) { ++ name = NULL; ++ } else { ++ name = strdup(princ); ++ if (!name) { ++ printerr(0, "fail to dup str %s\n", princ); ++ fclose(f); ++ return -1; ++ } ++ } ++ if (!strcmp(nid_str, "*")) { ++ nid = LNET_NID_ANY; ++ } else { ++ nid = libcfs_str2nid(nid_str); ++ if (nid == LNET_NID_ANY) { ++ printerr(0, "fail to parse nid %s\n", nid_str); ++ fclose(f); ++ return -1; ++ } ++ } ++ dest_uid = parse_uid(dest); ++ if (dest_uid == -1) { ++ printerr(0, "no valid user: %s\n", dest); ++ free(name); ++ fclose(f); ++ return -1; ++ } ++ ++ mapping.items[mapping.nitems].principal = name; ++ mapping.items[mapping.nitems].nid = nid; ++ mapping.items[mapping.nitems].uid = dest_uid; ++ mapping.nitems++; ++ printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n", ++ name ? name : "*", nid_str, nid, dest_uid); ++ } ++ ++ return 0; ++} ++ ++static inline int mapping_changed(void) ++{ ++ struct stat st; ++ ++ if (stat(MAPPING_DATABASE_FILE, &st) == -1) { ++ /* stat failed, treat it like doesn't exist or be removed */ ++ if (mapping_mtime == 0) { ++ return 0; ++ } else { ++ printerr(0, "Warning: stat %s failed: %s\n", ++ MAPPING_DATABASE_FILE, strerror(errno)); ++ ++ mapping_mtime = 0; ++ return 1; ++ } ++ } ++ ++ if (st.st_mtime != mapping_mtime) { ++ mapping_mtime = st.st_mtime; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid) ++{ ++ int n; ++ ++ /* FIXME race condition here */ ++ if (mapping_changed()) { ++ if (read_mapping_db()) ++ printerr(0, "all remote users will be denied\n"); ++ } ++ ++ for (n = 0; n < mapping.nitems; n++) { ++ struct user_map_item *entry = &mapping.items[n]; ++ ++ if (entry->nid != LNET_NID_ANY && entry->nid != nid) ++ continue; ++ if (!entry->principal || ++ !strcasecmp(entry->principal, princ)) { ++ printerr(1, "found mapping: %s ==> %d\n", ++ princ, entry->uid); ++ *uid = entry->uid; ++ return 0; ++ } ++ } ++ printerr(2, "no mapping for %s/%#Lx\n", princ, nid); ++ *uid = -1; ++ return -1; ++} ++ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/lsupport.h nfs-utils-1.0.10/utils/gssd/lsupport.h +--- nfs-utils-1.0.10.orig/utils/gssd/lsupport.h 2006-11-15 21:41:23.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/lsupport.h 2006-11-15 21:44:43.000000000 -0700 +@@ -0,0 +1,89 @@ ++/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- ++ * vim:expandtab:shiftwidth=8:tabstop=8: ++ */ ++ ++#ifndef __LIBCFS_H__ ++#define __LIBCFS_H__ ++ ++#include ++#include ++ ++#define GSSD_CLI (0) ++#define GSSD_SVC (1) ++ ++void gssd_init_unique(int type); ++void gssd_exit_unique(int type); ++ ++/* ++ * copied from lustre source ++ */ ++ ++#define LUSTRE_GSS_SVC_MDS 0 ++#define LUSTRE_GSS_SVC_OSS 1 ++ ++struct lgssd_upcall_data { ++ uint32_t seq; ++ uint32_t uid; ++ uint32_t gid; ++ uint32_t svc; ++ uint64_t nid; ++ uint64_t pag; ++ char obd[64]; ++}; + -+static -+int read_mapping_db(void) -+{ -+ char princ[MAX_LINE_LEN]; -+ char nid_str[MAX_LINE_LEN]; -+ char dest[MAX_LINE_LEN]; -+ lnet_nid_t nid; -+ uid_t dest_uid; -+ FILE *f; -+ char *line, linebuf[MAX_LINE_LEN]; ++#define GSSD_INTERFACE_VERSION (1) + -+ /* cleanup old mappings */ -+ cleanup_mapping(); ++struct lgssd_ioctl_param { ++ int version; /* in */ ++ char *uuid; /* in */ ++ int lustre_svc; /* in */ ++ uid_t uid; /* in */ ++ gid_t gid; /* in */ ++ long send_token_size;/* in */ ++ char *send_token; /* in */ ++ long reply_buf_size; /* in */ ++ char *reply_buf; /* in */ ++ long status; /* out */ ++ long reply_length; /* out */ ++}; + -+ f = fopen(MAPPING_DATABASE_FILE, "r"); -+ if (!f) { -+ printerr(0, "can't open mapping database: %s\n", -+ MAPPING_DATABASE_FILE); -+ return -1; -+ } ++#define GSSD_DEFAULT_GETHOSTNAME_EX "/etc/lustre/nid2hostname" ++#define MAPPING_DATABASE_FILE "/etc/lustre/idmap.conf" + -+ while ((line = fgets(linebuf, MAX_LINE_LEN, f))) { -+ char *name; ++typedef uint64_t lnet_nid_t; ++typedef uint32_t lnet_netid_t; + -+ if (strlen(line) >= MAX_LINE_LEN) { -+ printerr(0, "invalid mapping db: line too long (%d)\n", -+ strlen(line)); -+ cleanup_mapping(); -+ fclose(f); -+ return -1; -+ } -+ if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) { -+ printerr(0, "mapping db: syntax error\n"); -+ cleanup_mapping(); -+ fclose(f); -+ return -1; -+ } -+ if (grow_mapping(mapping.nitems + 1)) { -+ printerr(0, "fail to grow mapping to %d\n", -+ mapping.nitems + 1); -+ fclose(f); -+ return -1; -+ } -+ if (!strcmp(princ, "*")) { -+ name = NULL; -+ } else { -+ name = strdup(princ); -+ if (!name) { -+ printerr(0, "fail to dup str %s\n", princ); -+ fclose(f); -+ return -1; -+ } -+ } -+ if (!strcmp(nid_str, "*")) { -+ nid = LNET_NID_ANY; -+ } else { -+ nid = libcfs_str2nid(nid_str); -+ if (nid == LNET_NID_ANY) { -+ printerr(0, "fail to parse nid %s\n", nid_str); -+ fclose(f); -+ return -1; -+ } -+ } -+ dest_uid = parse_uid(dest); -+ if (dest_uid == -1) { -+ printerr(0, "no valid user: %s\n", dest); -+ free(name); -+ fclose(f); -+ return -1; -+ } ++#define LNET_NID_ANY ((lnet_nid_t) -1) ++#define LNET_PID_ANY ((lnet_pid_t) -1) + -+ mapping.items[mapping.nitems].principal = name; -+ mapping.items[mapping.nitems].nid = nid; -+ mapping.items[mapping.nitems].uid = dest_uid; -+ mapping.nitems++; -+ printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n", -+ name ? name : "*", nid_str, nid, dest_uid); -+ } ++enum { ++ /* Only add to these values (i.e. don't ever change or redefine them): ++ * network addresses depend on them... */ ++ QSWLND = 1, ++ SOCKLND = 2, ++ GMLND = 3, ++ PTLLND = 4, ++ O2IBLND = 5, ++ CIBLND = 6, ++ OPENIBLND = 7, ++ IIBLND = 8, ++ LOLND = 9, ++ RALND = 10, ++ VIBLND = 11, ++ LND_ENUM_END_MARKER ++}; + -+ return 0; -+} ++int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen); ++int lookup_mapping(char *princ, uint64_t nid, uid_t *uid); ++lnet_nid_t libcfs_str2nid(char *str); + -+static inline int mapping_changed(void) ++/* how an LNET NID encodes net:address */ ++#define LNET_NIDADDR(nid) ((uint32_t)((nid) & 0xffffffff)) ++#define LNET_NIDNET(nid) ((uint32_t)(((nid) >> 32)) & 0xffffffff) ++#define LNET_MKNID(net,addr) ((((uint64_t)(net))<<32)|((uint64_t)(addr))) ++/* how net encodes type:number */ ++#define LNET_NETNUM(net) ((net) & 0xffff) ++#define LNET_NETTYP(net) (((net) >> 16) & 0xffff) ++#define LNET_MKNET(typ,num) ((((uint32_t)(typ))<<16)|((uint32_t)(num))) ++ ++#endif /* __LIBCFS_H__ */ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/Makefile.am nfs-utils-1.0.10/utils/gssd/Makefile.am +--- nfs-utils-1.0.10.orig/utils/gssd/Makefile.am 2006-11-15 21:26:08.000000000 -0700 ++++ nfs-utils-1.0.10/utils/gssd/Makefile.am 2006-11-15 21:44:43.000000000 -0700 +@@ -1,17 +1,11 @@ + ## Process this file with automake to produce Makefile.in + +-man8_MANS = gssd.man svcgssd.man +- +-RPCPREFIX = rpc. ++RPCPREFIX = + KPREFIX = @kprefix@ +-sbin_PREFIXED = gssd svcgssd +-sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err ++sbin_PREFIXED = lgssd lsvcgssd ++sbin_PROGRAMS = $(sbin_PREFIXED) + sbin_SCRIPTS = gss_destroy_creds + +-EXTRA_DIST = \ +- gss_destroy_creds \ +- $(man8_MANS) +- + COMMON_SRCS = \ + context.c \ + context_mit.c \ +@@ -21,13 +15,15 @@ COMMON_SRCS = \ + gss_util.c \ + gss_oids.c \ + err_util.c \ ++ lsupport.c \ + \ + context.h \ + err_util.h \ + gss_oids.h \ +- gss_util.h ++ gss_util.h \ ++ lsupport.h + +-gssd_SOURCES = \ ++lgssd_SOURCES = \ + $(COMMON_SRCS) \ + gssd.c \ + gssd_main_loop.c \ +@@ -38,13 +34,12 @@ gssd_SOURCES = \ + krb5_util.h \ + write_bytes.h + +-gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS) +-gssd_LDFLAGS = $(KRBLDFLAGS) ++lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) ++lgssd_LDFLAGS = $(KRBLDFLAGS) + +-gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ +- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) ++lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) + +-svcgssd_SOURCES = \ ++lsvcgssd_SOURCES = \ + $(COMMON_SRCS) \ + cacheio.c \ + svcgssd.c \ +@@ -55,20 +50,11 @@ svcgssd_SOURCES = \ + cacheio.h \ + svcgssd.h + +-svcgssd_LDADD = \ +- ../../support/nfs/libnfs.a \ +- $(RPCSECGSS_LIBS) -lnfsidmap \ +- $(KRBLIBS) +- +-svcgssd_LDFLAGS = $(KRBLDFLAGS) +- +-svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ +- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) ++lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) + +-gss_clnt_send_err_SOURCES = gss_clnt_send_err.c ++lsvcgssd_LDFLAGS = $(KRBLDFLAGS) + +-gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ +- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) ++lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) + + MAINTAINERCLEANFILES = Makefile.in + +@@ -92,23 +78,3 @@ uninstall-hook: + done) + + +-# XXX This makes some assumptions about what automake does. +-# XXX But there is no install-man-hook or install-man-local. +-install-man: install-man8 install-man-links +-uninstall-man: uninstall-man8 uninstall-man-links +- +-install-man-links: +- (cd $(DESTDIR)$(man8dir) && \ +- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ +- inst=`echo $$m | sed -e 's/man$$/8/'`; \ +- rm -f $(RPCPREFIX)$$inst ; \ +- $(LN_S) $$inst $(RPCPREFIX)$$inst ; \ +- done) +- +-uninstall-man-links: +- (cd $(DESTDIR)$(man8dir) && \ +- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ +- inst=`echo $$m | sed -e 's/man$$/8/'`; \ +- rm -f $(RPCPREFIX)$$inst ; \ +- done) +- +diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd.c nfs-utils-1.0.10/utils/gssd/svcgssd.c +--- nfs-utils-1.0.10.orig/utils/gssd/svcgssd.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/svcgssd.c 2006-11-15 21:44:43.000000000 -0700 +@@ -43,7 +43,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -54,11 +53,33 @@ + #include + #include + #include +-#include "nfslib.h" ++#include + #include "svcgssd.h" + #include "gss_util.h" + #include "err_util.h" ++#include "lsupport.h" + ++void ++closeall(int min) +{ -+ struct stat st; -+ -+ if (stat(MAPPING_DATABASE_FILE, &st) == -1) { -+ /* stat failed, treat it like doesn't exist or be removed */ -+ if (mapping_mtime == 0) { -+ return 0; -+ } else { -+ printerr(0, "Warning: stat %s failed: %s\n", -+ MAPPING_DATABASE_FILE, strerror(errno)); -+ -+ mapping_mtime = 0; -+ return 1; -+ } -+ } -+ -+ if (st.st_mtime != mapping_mtime) { -+ mapping_mtime = st.st_mtime; -+ return 1; -+ } ++ DIR *dir = opendir("/proc/self/fd"); ++ if (dir != NULL) { ++ int dfd = dirfd(dir); ++ struct dirent *d; + -+ return 0; ++ while ((d = readdir(dir)) != NULL) { ++ char *endp; ++ long n = strtol(d->d_name, &endp, 10); ++ if (*endp != '\0' && n >= min && n != dfd) ++ (void) close(n); ++ } ++ closedir(dir); ++ } else { ++ int fd = sysconf(_SC_OPEN_MAX); ++ while (--fd >= min) ++ (void) close(fd); ++ } +} + /* + * mydaemon creates a pipe between the partent and child + * process. The parent process will wait until the +@@ -165,8 +186,8 @@ main(int argc, char *argv[]) + int get_creds = 1; + int fg = 0; + int verbosity = 0; +- int rpc_verbosity = 0; + int opt; ++ int must_srv_mds = 0, must_srv_oss = 0; + extern char *optarg; + char *progname; + +@@ -181,8 +202,13 @@ main(int argc, char *argv[]) + case 'v': + verbosity++; + break; +- case 'r': +- rpc_verbosity++; ++ case 'm': ++ get_creds = 1; ++ must_srv_mds = 1; ++ break; ++ case 'o': ++ get_creds = 1; ++ must_srv_oss = 1; + break; + default: + usage(argv[0]); +@@ -196,27 +222,13 @@ main(int argc, char *argv[]) + progname = argv[0]; + + initerr(progname, verbosity, fg); +-#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL +- authgss_set_debug_level(rpc_verbosity); +-#else +- if (rpc_verbosity > 0) +- printerr(0, "Warning: rpcsec_gss library does not " +- "support setting debug level\n"); +-#endif + + if (gssd_check_mechs() != 0) { + printerr(0, "ERROR: Problem with gssapi library\n"); + exit(1); + } + +- if (!fg) +- mydaemon(0, 0); +- +- signal(SIGINT, sig_die); +- signal(SIGTERM, sig_die); +- signal(SIGHUP, sig_hup); +- +- if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) { ++ if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) { + printerr(0, "unable to obtain root (machine) credentials\n"); + printerr(0, "do you have a keytab entry for " + "nfs/@ in " +@@ -225,9 +237,18 @@ main(int argc, char *argv[]) + } + + if (!fg) ++ mydaemon(0, 0); + -+int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid) -+{ -+ int n; ++ signal(SIGINT, sig_die); ++ signal(SIGTERM, sig_die); ++ signal(SIGHUP, sig_hup); + -+ /* FIXME race condition here */ -+ if (mapping_changed()) { -+ if (read_mapping_db()) -+ printerr(0, "all remote users will be denied\n"); -+ } ++ if (!fg) + release_parent(); + +- gssd_run(); ++ gssd_init_unique(GSSD_SVC); + -+ for (n = 0; n < mapping.nitems; n++) { -+ struct user_map_item *entry = &mapping.items[n]; ++ svcgssd_run(); + printerr(0, "gssd_run returned!\n"); + abort(); + } +diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd.h nfs-utils-1.0.10/utils/gssd/svcgssd.h +--- nfs-utils-1.0.10.orig/utils/gssd/svcgssd.h 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/svcgssd.h 2006-11-15 21:44:43.000000000 -0700 +@@ -36,8 +36,19 @@ + #include + + void handle_nullreq(FILE *f); +-void gssd_run(void); ++void svcgssd_run(void); ++int gssd_prepare_creds(int must_srv_mds, int must_srv_oss); ++gss_cred_id_t gssd_select_svc_cred(int lustre_svc); + +-#define GSSD_SERVICE_NAME "nfs" ++extern char *mds_local_realm; ++extern char *oss_local_realm; + -+ if (entry->nid != LNET_NID_ANY && entry->nid != nid) -+ continue; -+ if (!entry->principal || -+ !strcasecmp(entry->principal, princ)) { -+ printerr(1, "found mapping: %s ==> %d\n", -+ princ, entry->uid); -+ *uid = entry->uid; -+ return 0; -+ } -+ } -+ printerr(2, "no mapping for %s/%#Lx\n", princ, nid); -+ *uid = -1; -+ return -1; -+} ++#define GSSD_SERVICE_NAME "lustre" + ---- nfs-utils-1.0.10/utils/gssd/err_util.h.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/err_util.h 2006-10-30 16:40:47.000000000 -0700 -@@ -33,5 +33,6 @@ - - void initerr(char *progname, int verbosity, int fg); - void printerr(int priority, char *format, ...); -+void print_hexl(int pri, unsigned char *cp, int length); ++/* XXX */ ++#define GSSD_SERVICE_MDS "lustre_mds" ++#define GSSD_SERVICE_OSS "lustre_oss" ++#define LUSTRE_ROOT_NAME "lustre_root" ++#define LUSTRE_ROOT_NAMELEN 11 - #endif /* _ERR_UTIL_H_ */ ---- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c 2006-10-30 16:40:47.000000000 -0700 + #endif /* _RPC_SVCGSSD_H_ */ +diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c +--- nfs-utils-1.0.10.orig/utils/gssd/svcgssd_main_loop.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c 2006-11-15 21:44:43.000000000 -0700 @@ -47,31 +47,31 @@ #include "err_util.h" @@ -3139,193 +3255,338 @@ if (ret < 0) { if (save_err != EINTR) printerr(0, "error return from poll: %s\n", -@@ -87,5 +87,6 @@ +@@ -87,5 +87,6 @@ gssd_run() if (pollfd.revents & POLLIN) handle_nullreq(f); } + fclose(f); } } ---- nfs-utils-1.0.10/utils/gssd/Makefile.am.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/Makefile.am 2006-10-30 16:40:47.000000000 -0700 -@@ -1,17 +1,11 @@ - ## Process this file with automake to produce Makefile.in +diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c +--- nfs-utils-1.0.10.orig/utils/gssd/svcgssd_proc.c 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-11-15 21:44:43.000000000 -0700 +@@ -35,7 +35,6 @@ --man8_MANS = gssd.man svcgssd.man -- --RPCPREFIX = rpc. -+RPCPREFIX = - KPREFIX = @kprefix@ --sbin_PREFIXED = gssd svcgssd --sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err -+sbin_PREFIXED = lgssd lsvcgssd -+sbin_PROGRAMS = $(sbin_PREFIXED) - sbin_SCRIPTS = gss_destroy_creds + #include + #include +-#include --EXTRA_DIST = \ -- gss_destroy_creds \ -- $(man8_MANS) -- - COMMON_SRCS = \ - context.c \ - context_mit.c \ -@@ -20,13 +14,15 @@ - gss_util.c \ - gss_oids.c \ - err_util.c \ -+ lsupport.c \ - \ - context.h \ - err_util.h \ - gss_oids.h \ -- gss_util.h -+ gss_util.h \ -+ lsupport.h + #include + #include +@@ -44,25 +43,28 @@ + #include + #include + #include +-#include ++#include --gssd_SOURCES = \ -+lgssd_SOURCES = \ - $(COMMON_SRCS) \ - gssd.c \ - gssd_main_loop.c \ -@@ -37,13 +33,12 @@ - krb5_util.h \ - write_bytes.h + #include "svcgssd.h" + #include "gss_util.h" + #include "err_util.h" + #include "context.h" + #include "cacheio.h" ++#include "lsupport.h" --gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS) --gssd_LDFLAGS = $(KRBLDFLAGS) -+lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) -+lgssd_LDFLAGS = $(KRBLDFLAGS) + extern char * mech2file(gss_OID mech); +-#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel" +-#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel" ++#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel" ++#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.init/channel" --gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) + #define TOKEN_BUF_SIZE 8192 --svcgssd_SOURCES = \ -+lsvcgssd_SOURCES = \ - $(COMMON_SRCS) \ - cacheio.c \ - svcgssd.c \ -@@ -54,20 +49,11 @@ - cacheio.h \ - svcgssd.h + struct svc_cred { +- uid_t cr_uid; +- gid_t cr_gid; +- int cr_ngroups; +- gid_t cr_groups[NGROUPS]; ++ uint32_t cr_remote; ++ uint32_t cr_usr_root; ++ uint32_t cr_usr_mds; ++ uid_t cr_uid; ++ uid_t cr_mapped_uid; ++ uid_t cr_gid; + }; --svcgssd_LDADD = \ -- ../../support/nfs/libnfs.a \ -- $(RPCSECGSS_LIBS) -lnfsidmap \ -- $(KRBLIBS) -- --svcgssd_LDFLAGS = $(KRBLDFLAGS) -- --svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) + static int +@@ -70,10 +72,9 @@ do_svc_downcall(gss_buffer_desc *out_han + gss_OID mech, gss_buffer_desc *context_token) + { + FILE *f; +- int i; + char *fname = NULL; --gss_clnt_send_err_SOURCES = gss_clnt_send_err.c -+lsvcgssd_LDFLAGS = $(KRBLDFLAGS) +- printerr(1, "doing downcall\n"); ++ printerr(2, "doing downcall\n"); + if ((fname = mech2file(mech)) == NULL) + goto out_err; + f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w"); +@@ -86,11 +87,12 @@ do_svc_downcall(gss_buffer_desc *out_han + qword_printhex(f, out_handle->value, out_handle->length); + /* XXX are types OK for the rest of this? */ + qword_printint(f, 0x7fffffff); /*XXX need a better timeout */ ++ qword_printint(f, cred->cr_remote); ++ qword_printint(f, cred->cr_usr_root); ++ qword_printint(f, cred->cr_usr_mds); ++ qword_printint(f, cred->cr_mapped_uid); + qword_printint(f, cred->cr_uid); + qword_printint(f, cred->cr_gid); +- qword_printint(f, cred->cr_ngroups); +- for (i=0; i < cred->cr_ngroups; i++) +- qword_printint(f, cred->cr_groups[i]); + qword_print(f, fname); + qword_printhex(f, context_token->value, context_token->length); + qword_eol(f); +@@ -119,7 +121,7 @@ send_response(FILE *f, gss_buffer_desc * + /* XXXARG: */ + int g; --gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) +- printerr(1, "sending null reply\n"); ++ printerr(2, "sending null reply\n"); - MAINTAINERCLEANFILES = Makefile.in + qword_addhex(&bp, &blen, in_handle->value, in_handle->length); + qword_addhex(&bp, &blen, in_token->value, in_token->length); +@@ -159,6 +161,7 @@ send_response(FILE *f, gss_buffer_desc * + #define rpcsec_gsserr_credproblem 13 + #define rpcsec_gsserr_ctxproblem 14 -@@ -91,23 +77,3 @@ - done) ++#if 0 + static void + add_supplementary_groups(char *secname, char *name, struct svc_cred *cred) + { +@@ -182,7 +185,9 @@ add_supplementary_groups(char *secname, + } + } + } ++#endif ++#if 0 + static int + get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred) + { +@@ -248,7 +253,9 @@ out_free: + out: + return res; + } ++#endif --# XXX This makes some assumptions about what automake does. --# XXX But there is no install-man-hook or install-man-local. --install-man: install-man8 install-man-links --uninstall-man: uninstall-man8 uninstall-man-links -- --install-man-links: -- (cd $(DESTDIR)$(man8dir) && \ -- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ -- inst=`echo $$m | sed -e 's/man$$/8/'`; \ -- rm -f $(RPCPREFIX)$$inst ; \ -- $(LN_S) $$inst $(RPCPREFIX)$$inst ; \ -- done) -- --uninstall-man-links: -- (cd $(DESTDIR)$(man8dir) && \ -- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ -- inst=`echo $$m | sed -e 's/man$$/8/'`; \ -- rm -f $(RPCPREFIX)$$inst ; \ -- done) -- ---- nfs-utils-1.0.10/utils/gssd/gssd.h.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/gssd.h 2006-10-30 16:40:47.000000000 -0700 -@@ -48,8 +48,13 @@ - #define GSSD_DEFAULT_CRED_PREFIX "krb5cc_" - #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine" - #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab" --#define GSSD_SERVICE_NAME "nfs" --#define GSSD_SERVICE_NAME_LEN 3 -+#define GSSD_SERVICE_MDS "lustre_mds" -+#define GSSD_SERVICE_OSS "lustre_oss" -+#define GSSD_SERVICE_MDS_NAMELEN 10 -+#define GSSD_SERVICE_OSS_NAMELEN 10 ++#if 0 + void + print_hexl(int pri, unsigned char *cp, int length) + { +@@ -285,12 +292,113 @@ print_hexl(int pri, unsigned char *cp, i + printerr(pri,"\n"); + } + } ++#endif + -+#define LUSTRE_ROOT_NAME "lustre_root" -+#define LUSTRE_ROOT_NAMELEN 11 ++static int ++get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, ++ lnet_nid_t nid, uint32_t lustre_svc) ++{ ++ u_int32_t maj_stat, min_stat; ++ gss_buffer_desc name; ++ char *sname, *realm, *slash; ++ int res = -1; ++ gss_OID name_type = GSS_C_NO_OID; ++ struct passwd *pw; ++ ++ memset(cred, 0, sizeof(*cred)); ++ ++ maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type); ++ if (maj_stat != GSS_S_COMPLETE) { ++ pgsserr("get_ids: gss_display_name", ++ maj_stat, min_stat, mech); ++ return -1; ++ } ++ if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */ ++ !(sname = calloc(name.length + 1, 1))) { ++ printerr(0, "WARNING: get_ids: error allocating %d bytes " ++ "for sname\n", name.length + 1); ++ gss_release_buffer(&min_stat, &name); ++ return -1; ++ } ++ memcpy(sname, name.value, name.length); ++ printerr(1, "authenticated %s from %016llx\n", sname, nid); ++ gss_release_buffer(&min_stat, &name); ++ ++ if (lustre_svc == LUSTRE_GSS_SVC_MDS) ++ lookup_mapping(sname, nid, &cred->cr_mapped_uid); ++ else ++ cred->cr_mapped_uid = -1; ++ ++ realm = strchr(sname, '@'); ++ if (!realm) { ++ printerr(0, "WARNNING: principal %s contains no realm name\n", ++ sname); ++ cred->cr_remote = (mds_local_realm != NULL); ++ } else { ++ *realm++ = '\0'; ++ if (!mds_local_realm) ++ cred->cr_remote = 1; ++ else ++ cred->cr_remote = ++ (strcasecmp(mds_local_realm, realm) != 0); ++ } ++ ++ if (cred->cr_remote) { ++ if (cred->cr_mapped_uid != -1) ++ res = 0; ++ else ++ printerr(0, "principal %s is remote without mapping\n", ++ sname); ++ goto out_free; ++ } ++ ++ slash = strchr(sname, '/'); ++ if (slash) ++ *slash = '\0'; ++ ++ if (!(pw = getpwnam(sname))) { ++ /* If client use machine credential, we map it to root, which ++ * will subject to further mapping by root-squash in kernel. ++ * ++ * MDS service keytab is treated as special user, also mapped ++ * to root. OSS service keytab can't be used as a user. ++ */ ++ if (!strcmp(sname, LUSTRE_ROOT_NAME)) { ++ printerr(2, "lustre_root principal, resolve to uid 0\n"); ++ cred->cr_uid = 0; ++ cred->cr_usr_root = 1; ++ } else if (!strcmp(sname, GSSD_SERVICE_MDS)) { ++ printerr(2, "mds service principal, resolve to uid 0\n"); ++ cred->cr_uid = 0; ++ cred->cr_usr_mds = 1; ++ } else { ++ cred->cr_uid = -1; ++ if (cred->cr_mapped_uid == -1) { ++ printerr(0, "invalid user %s\n", sname); ++ goto out_free; ++ } ++ printerr(2, "user %s mapped to %u\n", ++ sname, cred->cr_mapped_uid); ++ } ++ } else { ++ cred->cr_uid = pw->pw_uid; ++ printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid); ++ } ++ ++ res = 0; ++out_free: ++ free(sname); ++ return res; ++} ++ ++typedef struct gss_union_ctx_id_t { ++ gss_OID mech_type; ++ gss_ctx_id_t internal_ctx_id; ++} gss_union_ctx_id_desc, *gss_union_ctx_id_t; - /* - * The gss mechanisms that we can handle -@@ -61,6 +66,7 @@ - extern char pipefsdir[PATH_MAX]; - extern char keytabfile[PATH_MAX]; - extern char ccachedir[PATH_MAX]; -+extern char gethostname_ex[PATH_MAX]; + void + handle_nullreq(FILE *f) { +- /* XXX initialize to a random integer to reduce chances of unnecessary +- * invalidation of existing ctx's on restarting svcgssd. */ +- static u_int32_t handle_seq = 0; ++ uint64_t handle_seq; + char in_tok_buf[TOKEN_BUF_SIZE]; + char in_handle_buf[15]; + char out_handle_buf[15]; +@@ -302,10 +410,13 @@ handle_nullreq(FILE *f) { + ignore_out_tok = {.value = NULL}, + /* XXX isn't there a define for this?: */ + null_token = {.value = NULL}; ++ uint32_t lustre_svc; ++ lnet_nid_t nid; + u_int32_t ret_flags; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_name_t client_name; + gss_OID mech = GSS_C_NO_OID; ++ gss_cred_id_t svc_cred; + u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0; + u_int32_t ignore_min_stat; + struct svc_cred cred; +@@ -313,7 +424,7 @@ handle_nullreq(FILE *f) { + static int lbuflen = 0; + static char *cp; - TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list; +- printerr(1, "handling null request\n"); ++ printerr(2, "handling null request\n"); -@@ -69,10 +75,6 @@ - char *dirname; - int dir_fd; - char *servicename; -- char *servername; -- int prog; -- int vers; -- char *protocol; - int krb5_fd; - int krb5_poll_index; - int spkm3_fd; -@@ -83,8 +85,7 @@ - int update_client_list(void); - void handle_krb5_upcall(struct clnt_info *clp); - void handle_spkm3_upcall(struct clnt_info *clp); --int gssd_acquire_cred(char *server_name); --void gssd_run(void); -+void lgssd_run(void); + if (readline(fileno(f), &lbuf, &lbuflen) != 1) { + printerr(0, "WARNING: handle_nullreq: " +@@ -323,15 +434,21 @@ handle_nullreq(FILE *f) { + + cp = lbuf; ++ qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc)); ++ qword_get(&cp, (char *) &nid, sizeof(nid)); ++ qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq)); ++ printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n", ++ lustre_svc, nid, handle_seq); ++ + in_handle.length = (size_t) qword_get(&cp, in_handle.value, + sizeof(in_handle_buf)); +- printerr(2, "in_handle: \n"); +- print_hexl(2, in_handle.value, in_handle.length); ++ printerr(3, "in_handle: \n"); ++ print_hexl(3, in_handle.value, in_handle.length); - #endif /* _RPC_GSSD_H_ */ ---- nfs-utils-1.0.10/utils/gssd/svcgssd.h.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/gssd/svcgssd.h 2006-10-30 16:40:47.000000000 -0700 -@@ -36,8 +36,19 @@ - #include + in_tok.length = (size_t) qword_get(&cp, in_tok.value, + sizeof(in_tok_buf)); +- printerr(2, "in_tok: \n"); +- print_hexl(2, in_tok.value, in_tok.length); ++ printerr(3, "in_tok: \n"); ++ print_hexl(3, in_tok.value, in_tok.length); - void handle_nullreq(FILE *f); --void gssd_run(void); -+void svcgssd_run(void); -+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss); -+gss_cred_id_t gssd_select_svc_cred(int lustre_svc); + if (in_tok.length < 0) { + printerr(0, "WARNING: handle_nullreq: " +@@ -351,7 +468,13 @@ handle_nullreq(FILE *f) { + memcpy(&ctx, in_handle.value, in_handle.length); + } --#define GSSD_SERVICE_NAME "nfs" -+extern char *mds_local_realm; -+extern char *oss_local_realm; +- maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds, ++ svc_cred = gssd_select_svc_cred(lustre_svc); ++ if (!svc_cred) { ++ printerr(0, "no service credential for svc %u\n", lustre_svc); ++ goto out_err; ++ } + -+#define GSSD_SERVICE_NAME "lustre" ++ maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred, + &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name, + &mech, &out_tok, &ret_flags, NULL, NULL); + +@@ -369,7 +492,8 @@ handle_nullreq(FILE *f) { + maj_stat, min_stat, mech); + goto out_err; + } +- if (get_ids(client_name, mech, &cred)) { + -+/* XXX */ -+#define GSSD_SERVICE_MDS "lustre_mds" -+#define GSSD_SERVICE_OSS "lustre_oss" -+#define LUSTRE_ROOT_NAME "lustre_root" -+#define LUSTRE_ROOT_NAMELEN 11 ++ if (get_ids(client_name, mech, &cred, nid, lustre_svc)) { + /* get_ids() prints error msg */ + maj_stat = GSS_S_BAD_NAME; /* XXX ? */ + gss_release_name(&ignore_min_stat, &client_name); +@@ -377,10 +501,8 @@ handle_nullreq(FILE *f) { + } + gss_release_name(&ignore_min_stat, &client_name); - #endif /* _RPC_SVCGSSD_H_ */ ---- nfs-utils-1.0.10/utils/Makefile.am.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/utils/Makefile.am 2006-10-30 16:40:47.000000000 -0700 +- + /* Context complete. Pass handle_seq in out_handle to use + * for context lookup in the kernel. */ +- handle_seq++; + out_handle.length = sizeof(handle_seq); + memcpy(out_handle.value, &handle_seq, sizeof(handle_seq)); + +@@ -404,7 +526,6 @@ out: + free(ctx_token.value); + if (out_tok.value != NULL) + gss_release_buffer(&ignore_min_stat, &out_tok); +- printerr(1, "finished handling null request\n"); + return; + + out_err: +diff -rup nfs-utils-1.0.10.orig/utils/Makefile.am nfs-utils-1.0.10/utils/Makefile.am +--- nfs-utils-1.0.10.orig/utils/Makefile.am 2006-08-07 00:40:50.000000000 -0600 ++++ nfs-utils-1.0.10/utils/Makefile.am 2006-11-15 21:44:43.000000000 -0700 @@ -2,31 +2,6 @@ OPTDIRS = @@ -3359,206 +3620,3 @@ +SUBDIRS = gssd MAINTAINERCLEANFILES = Makefile.in ---- nfs-utils-1.0.10/configure.in.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/configure.in 2006-10-30 16:40:47.000000000 -0700 -@@ -17,61 +17,14 @@ - RELEASE=$withval, - RELEASE=1) - AC_SUBST(RELEASE) --AC_ARG_WITH(statedir, -- [ --with-statedir=/foo use state dir /foo [/var/lib/nfs]], -- statedir=$withval, -- statedir=/var/lib/nfs) -- AC_SUBST(statedir) --AC_ARG_WITH(statduser, -- [AC_HELP_STRING([--with-statduser=rpcuser], -- [statd to run under @<:@rpcuser or nobody@:>@] -- )], -- statduser=$withval, -- if test "x$cross_compiling" = "xno"; then -- if grep -s '^rpcuser:' /etc/passwd > /dev/null; then -- statduser=rpcuser -- else -- statduser=nobody -- fi -- else -- statduser=nobody -- fi) -- AC_SUBST(statduser) --AC_ARG_ENABLE(nfsv3, -- [AC_HELP_STRING([--enable-nfsv3], -- [enable support for NFSv3 @<:@default=yes@:>@])], -- enable_nfsv3=$enableval, -- enable_nfsv3=yes) -- if test "$enable_nfsv3" = yes; then -- AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in]) -- else -- enable_nfsv3= -- fi -- AC_SUBST(enable_nfsv3) --AC_ARG_ENABLE(nfsv4, -- [AC_HELP_STRING([--enable-nfsv4], -- [enable support for NFSv4 @<:@default=yes@:>@])], -- enable_nfsv4=$enableval, -- enable_nfsv4=yes) -- if test "$enable_nfsv4" = yes; then -- AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in]) -- IDMAPD=idmapd -- else -- enable_nfsv4= -- IDMAPD= -- fi -- AC_SUBST(IDMAPD) -- AC_SUBST(enable_nfsv4) -- AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"]) - AC_ARG_ENABLE(gss, - [AC_HELP_STRING([--enable-gss], - [enable support for rpcsec_gss @<:@default=yes@:>@])], - enable_gss=$enableval, - enable_gss=yes) - if test "$enable_gss" = yes; then -- AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in]) -- GSSD=gssd -- SVCGSSD=svcgssd -+ GSSD=lgssd -+ SVCGSSD=lsvcgssd - else - enable_gss= - GSSD= -@@ -81,38 +34,6 @@ - AC_SUBST(SVCGSSD) - AC_SUBST(enable_gss) - AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"]) --AC_ARG_ENABLE(kprefix, -- [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])], -- test "$enableval" = "yes" && kprefix=k, -- kprefix=) -- AC_SUBST(kprefix) --AC_ARG_ENABLE(secure-statd, -- [AC_HELP_STRING([--enable-secure-statd], -- [Only lockd can use statd (security)])], -- test "$enableval" = "yes" && secure_statd=yes, -- secure_statd=no) -- if test "$secure_statd" = yes; then -- AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.]) -- fi -- AC_SUBST(secure_statd) --AC_ARG_ENABLE(rquotad, -- [AC_HELP_STRING([--enable-rquotad], -- [enable rquotad @<:@default=yes@:>@])], -- enable_rquotad=$enableval, -- enable_rquotad=yes) -- if test "$enable_rquotad" = yes; then -- RQUOTAD=rquotad -- else -- RQUOTAD= -- fi -- AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"]) -- --AC_ARG_ENABLE(mount, -- [AC_HELP_STRING([--enable-mount], -- [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])], -- enable_mount=$enableval, -- enable_mount=no) -- AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"]) - - # Check whether user wants TCP wrappers support - AC_TCP_WRAPPERS -@@ -150,50 +71,18 @@ - AC_CHECK_LIB(socket, main, [LIBSOCKET="-lnsl"]) - AC_CHECK_LIB(nsl, main, [LIBNSL="-lnsl"]) - AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"]) --if test "$enable_nfsv4" = yes; then -- AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support])) -- AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) -- AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support])) -- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) -- dnl librpcsecgss already has a dependency on libgssapi, -- dnl but we need to make sure we get the right version - if test "$enable_gss" = yes; then -- PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, , -- [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss.]) -- AC_MSG_ERROR([If you have pkgconfig installed, you might try setting environment]) -- AC_MSG_ERROR([variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig]) -- ] -- ) - PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9) - fi - --fi --if test "$knfsd_cv_glibc2" = no; then -- AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"]) --fi - AC_SUBST(LIBSOCKET) - AC_SUBST(LIBNSL) - AC_SUBST(LIBCRYPT) - AC_SUBST(LIBBSD) - - if test "$enable_gss" = yes; then -- dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c -- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support])) -- AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support])) -- dnl the nfs4_set_debug function doesn't appear in all version of the library -- AC_CHECK_LIB(nfsidmap, nfs4_set_debug, -- AC_DEFINE(HAVE_NFS4_SET_DEBUG,1, -- [Whether nfs4_set_debug() is present in libnfsidmap]),) -- - dnl Check for Kerberos V5 - AC_KERBEROS_V5 -- -- dnl This is not done until here because we need to have KRBLIBS set -- dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS) -- AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl) -- AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level, -- AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl) -- - fi - - dnl ************************************************************* -@@ -305,35 +194,7 @@ - - AC_CONFIG_FILES([ - Makefile -- linux-nfs/Makefile -- support/Makefile -- support/export/Makefile -- support/include/nfs/Makefile -- support/include/rpcsvc/Makefile -- support/include/sys/fs/Makefile -- support/include/sys/Makefile -- support/include/Makefile -- support/misc/Makefile -- support/nfs/Makefile -- tools/Makefile -- tools/getiversion/Makefile -- tools/getkversion/Makefile -- tools/locktest/Makefile -- tools/nlmtest/Makefile -- tools/rpcdebug/Makefile -- tools/rpcgen/Makefile - utils/Makefile -- utils/exportfs/Makefile -- utils/gssd/Makefile -- utils/idmapd/Makefile -- utils/lockd/Makefile -- utils/mount/Makefile -- utils/mountd/Makefile -- utils/nfsd/Makefile -- utils/nfsstat/Makefile -- utils/nhfsstone/Makefile -- utils/rquotad/Makefile -- utils/showmount/Makefile -- utils/statd/Makefile]) -+ utils/gssd/Makefile]) - AC_OUTPUT - ---- nfs-utils-1.0.10/Makefile.am.lustre 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10/Makefile.am 2006-10-30 16:40:47.000000000 -0700 -@@ -1,6 +1,6 @@ - ## Process this file with automake to produce Makefile.in - --SUBDIRS = tools support utils linux-nfs -+SUBDIRS = utils - - MAINTAINERCLEANFILES = Makefile.in - diff --git a/lustre/utils/gss/svcgssd_mech2file.c b/lustre/utils/gss/svcgssd_mech2file.c index f44f7c6..22c3ed8 100644 --- a/lustre/utils/gss/svcgssd_mech2file.c +++ b/lustre/utils/gss/svcgssd_mech2file.c @@ -36,11 +36,7 @@ #include "config.h" -#ifdef HAVE_KRB5 -#include -#elif HAVE_HEIMDAL -#include -#endif +#include #include -- 1.8.3.1