Whamcloud - gitweb
LU-3289 gss: Interface and code changes for shared key 28/16728/17
authorJeremy Filizetti <jeremy.filizetti@gmail.com>
Tue, 6 Oct 2015 01:41:28 +0000 (21:41 -0400)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 13 Jun 2016 17:13:45 +0000 (17:13 +0000)
This patch moves and modifies some of the kerberos code to
be more general so it can be utilized by the sk and null
gss implementations.  This includes the userspace portion
for lsvcgssd and the kernel pipefs interface.  Since the gss
interface has changed the version has also been incremented.

Signed-off-by: Jeremy Filizetti <jeremy.filizetti@gmail.com>
Change-Id: Ib46b74c9b0e01c4f71f16d288eae83c5c1567bfb
Reviewed-on: http://review.whamcloud.com/16728
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
27 files changed:
lustre.spec.in
lustre/conf/Makefile.am
lustre/conf/lsvcgss [new file with mode: 0644]
lustre/include/lustre_nodemap.h
lustre/ptlrpc/gss/Makefile.in
lustre/ptlrpc/gss/gss_crypto.c [new file with mode: 0644]
lustre/ptlrpc/gss/gss_crypto.h [new file with mode: 0644]
lustre/ptlrpc/gss/gss_internal.h
lustre/ptlrpc/gss/gss_keyring.c
lustre/ptlrpc/gss/gss_krb5.h
lustre/ptlrpc/gss/gss_krb5_mech.c
lustre/ptlrpc/gss/gss_svc_upcall.c
lustre/scripts/lsvcgss
lustre/utils/gss/cacheio.c
lustre/utils/gss/cacheio.h
lustre/utils/gss/err_util.c
lustre/utils/gss/err_util.h
lustre/utils/gss/gssd_proc.c
lustre/utils/gss/lgss_keyring.c
lustre/utils/gss/lgss_utils.c
lustre/utils/gss/lgss_utils.h
lustre/utils/gss/lsupport.h
lustre/utils/gss/svcgssd.c
lustre/utils/gss/svcgssd.h
lustre/utils/gss/svcgssd_main_loop.c
lustre/utils/gss/svcgssd_mech2file.c
lustre/utils/gss/svcgssd_proc.c

index f20e064..ce40332 100644 (file)
@@ -337,6 +337,7 @@ echo '%{_sysconfdir}/ha.d/resource.d/Lustre' >>lustre.files
 # The following scripts are Red Hat specific
 %if %{with servers}
 echo '%{_sysconfdir}/sysconfig/lustre' >>lustre.files
+echo '%{_sysconfdir}/sysconfig/lsvcgss' >>lustre.files
 echo '%{_sysconfdir}/init.d/lustre' >>lustre.files
 %endif
 echo '%{_sysconfdir}/init.d/lnet' >>lustre.files
index 9dd742d..ce11fe9 100644 (file)
@@ -37,7 +37,7 @@
 #
 
 EXTRA_DIST = lustre.dtd slapd-lustre.conf lustre2ldif.xsl top.ldif \
-             99-lustre.rules lustre ldev.conf ko2iblnd.conf
+             99-lustre.rules lustre ldev.conf ko2iblnd.conf lsvcgss
 ldapconfdir = $(sysconfdir)/openldap
 
 if UTILS
@@ -51,7 +51,7 @@ udevrules_DATA = 99-lustre.rules
 if RHEL
 if SERVER
 sysconfigdir = $(sysconfdir)/sysconfig
-sysconfig_DATA = lustre
+sysconfig_DATA = lustre lsvcgss
 endif
 endif
 
diff --git a/lustre/conf/lsvcgss b/lustre/conf/lsvcgss
new file mode 100644 (file)
index 0000000..9f930e0
--- /dev/null
@@ -0,0 +1,2 @@
+# Optional arguments passed to lsvcgssd.
+LSVCGSSDARGS=''
index 82931c0..685e1d8 100644 (file)
@@ -28,6 +28,7 @@
 #define _LUSTRE_NODEMAP_H
 
 #include <lustre/lustre_idl.h>
+#include <lustre/lustre_user.h>
 
 #define LUSTRE_NODEMAP_NAME "nodemap"
 
@@ -132,7 +133,11 @@ __u32 nodemap_map_id(struct lu_nodemap *nodemap,
                     enum nodemap_tree_type tree_type, __u32 id);
 ssize_t nodemap_map_acl(struct lu_nodemap *nodemap, void *buf, size_t size,
                        enum nodemap_tree_type tree_type);
+#ifdef HAVE_SERVER_SUPPORT
 void nodemap_test_nid(lnet_nid_t nid, char *name_buf, size_t name_len);
+#else
+#define nodemap_test_nid(nid, name_buf, name_len) do {} while(0)
+#endif
 __u32 nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype,
                      __u32 client_id);
 struct nm_config_file *nm_config_file_register(const struct lu_env *env,
index 6eec564..bcc076c 100644 (file)
@@ -3,7 +3,7 @@ MODULES := ptlrpc_gss
 ptlrpc_gss-objs := sec_gss.o gss_bulk.o gss_cli_upcall.o gss_svc_upcall.o      \
                   gss_rawobj.o lproc_gss.o                                    \
                   gss_generic_token.o gss_mech_switch.o gss_krb5_mech.o       \
-                  gss_null_mech.o gss_sk_mech.o
+                  gss_null_mech.o gss_sk_mech.o gss_crypto.o
 
 @GSS_KEYRING_TRUE@ptlrpc_gss-objs += gss_keyring.o
 @GSS_PIPEFS_TRUE@ptlrpc_gss-objs += gss_pipefs.o
diff --git a/lustre/ptlrpc/gss/gss_crypto.c b/lustre/ptlrpc/gss/gss_crypto.c
new file mode 100644 (file)
index 0000000..2032f94
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * Modifications for Lustre
+ *
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Copyright (c) 2011, 2014, Intel Corporation.
+ *
+ * Author: Eric Mei <ericm@clusterfs.com>
+ */
+
+/*
+ *  linux/net/sunrpc/gss_krb5_mech.c
+ *  linux/net/sunrpc/gss_krb5_crypto.c
+ *  linux/net/sunrpc/gss_krb5_seal.c
+ *  linux/net/sunrpc/gss_krb5_seqnum.c
+ *  linux/net/sunrpc/gss_krb5_unseal.c
+ *
+ *  Copyright (c) 2001 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_SEC
+
+#include <libcfs/linux/linux-crypto.h>
+#include <obd.h>
+#include <obd_support.h>
+
+#include "gss_internal.h"
+#include "gss_crypto.h"
+
+int gss_keyblock_init(struct gss_keyblock *kb, char *alg_name,
+                     const int alg_mode)
+{
+       int rc;
+
+       kb->kb_tfm = crypto_alloc_blkcipher(alg_name, alg_mode, 0);
+       if (IS_ERR(kb->kb_tfm)) {
+               rc = PTR_ERR(kb->kb_tfm);
+               kb->kb_tfm = NULL;
+               CERROR("failed to alloc tfm: %s, mode %d: rc = %d\n", alg_name,
+                      alg_mode, rc);
+               return rc;
+       }
+
+       rc = crypto_blkcipher_setkey(kb->kb_tfm, kb->kb_key.data,
+                                    kb->kb_key.len);
+       if (rc) {
+               CERROR("failed to set %s key, len %d, rc = %d\n", alg_name,
+                      kb->kb_key.len, rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+void gss_keyblock_free(struct gss_keyblock *kb)
+{
+       rawobj_free(&kb->kb_key);
+       if (kb->kb_tfm)
+               crypto_free_blkcipher(kb->kb_tfm);
+}
+
+int gss_keyblock_dup(struct gss_keyblock *new, struct gss_keyblock *kb)
+{
+       return rawobj_dup(&new->kb_key, &kb->kb_key);
+}
+
+int gss_get_bytes(char **ptr, const char *end, void *res, size_t len)
+{
+       char *p, *q;
+       p = *ptr;
+       q = p + len;
+       if (q > end || q < p)
+               return -EINVAL;
+       memcpy(res, p, len);
+       *ptr = q;
+       return 0;
+}
+
+int gss_get_rawobj(char **ptr, const char *end, rawobj_t *res)
+{
+       char   *p, *q;
+       __u32   len;
+
+       p = *ptr;
+       if (gss_get_bytes(&p, end, &len, sizeof(len)))
+               return -EINVAL;
+
+       q = p + len;
+       if (q > end || q < p)
+               return -EINVAL;
+
+       /* Support empty objects */
+       if (len != 0) {
+               OBD_ALLOC_LARGE(res->data, len);
+               if (!res->data)
+                       return -ENOMEM;
+       } else {
+               res->len = len;
+               res->data = NULL;
+               return 0;
+       }
+
+       res->len = len;
+       memcpy(res->data, p, len);
+       *ptr = q;
+       return 0;
+}
+
+int gss_get_keyblock(char **ptr, const char *end,
+                    struct gss_keyblock *kb, __u32 keysize)
+{
+       char *buf;
+       int rc;
+
+       OBD_ALLOC_LARGE(buf, keysize);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       rc = gss_get_bytes(ptr, end, buf, keysize);
+       if (rc) {
+               OBD_FREE_LARGE(buf, keysize);
+               return rc;
+       }
+
+       kb->kb_key.len = keysize;
+       kb->kb_key.data = buf;
+       return 0;
+}
+
+/*
+ * Should be used for buffers allocated with k/vmalloc().
+ *
+ * Dispose of @sgt with gss_teardown_sgtable().
+ *
+ * @prealloc_sg is to avoid memory allocation inside sg_alloc_table()
+ * in cases where a single sg is sufficient.  No attempt to reduce the
+ * number of sgs by squeezing physically contiguous pages together is
+ * made though, for simplicity.
+ *
+ * This function is copied from the ceph filesystem code.
+ */
+int gss_setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg,
+                     const void *buf, unsigned int buf_len)
+{
+       struct scatterlist *sg;
+       const bool is_vmalloc = is_vmalloc_addr(buf);
+       unsigned int off = offset_in_page(buf);
+       unsigned int chunk_cnt = 1;
+       unsigned int chunk_len = PAGE_ALIGN(off + buf_len);
+       int i;
+       int rc;
+
+       if (buf_len == 0) {
+               memset(sgt, 0, sizeof(*sgt));
+               return -EINVAL;
+       }
+
+       if (is_vmalloc) {
+               chunk_cnt = chunk_len >> PAGE_SHIFT;
+               chunk_len = PAGE_SIZE;
+       }
+
+       if (chunk_cnt > 1) {
+               rc = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS);
+               if (rc)
+                       return rc;
+       } else {
+               WARN_ON_ONCE(chunk_cnt != 1);
+               sg_init_table(prealloc_sg, 1);
+               sgt->sgl = prealloc_sg;
+               sgt->nents = sgt->orig_nents = 1;
+       }
+
+       for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
+               struct page *page;
+               unsigned int len = min(chunk_len - off, buf_len);
+
+               if (is_vmalloc)
+                       page = vmalloc_to_page(buf);
+               else
+                       page = virt_to_page(buf);
+
+               sg_set_page(sg, page, len, off);
+
+               off = 0;
+               buf += len;
+               buf_len -= len;
+       }
+
+       WARN_ON_ONCE(buf_len != 0);
+
+       return 0;
+}
+
+void gss_teardown_sgtable(struct sg_table *sgt)
+{
+       if (sgt->orig_nents > 1)
+               sg_free_table(sgt);
+}
+
+int gss_crypt_generic(struct crypto_blkcipher *tfm, int decrypt, void *iv,
+                     void *in, void *out, int length)
+{
+       struct blkcipher_desc desc;
+       struct scatterlist sg;
+       struct sg_table sg_out;
+       __u8 local_iv[16] = {0};
+       __u32 ret = -EINVAL;
+
+       LASSERT(tfm);
+       desc.tfm = tfm;
+       desc.info = local_iv;
+       desc.flags = 0;
+
+       if (length % crypto_blkcipher_blocksize(tfm) != 0) {
+               CERROR("output length %d mismatch blocksize %d\n",
+                      length, crypto_blkcipher_blocksize(tfm));
+               goto out;
+       }
+
+       if (crypto_blkcipher_ivsize(tfm) > ARRAY_SIZE(local_iv)) {
+               CERROR("iv size too large %d\n", crypto_blkcipher_ivsize(tfm));
+               goto out;
+       }
+
+       if (iv)
+               memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm));
+
+       memcpy(out, in, length);
+
+       ret = gss_setup_sgtable(&sg_out, &sg, out, length);
+       if (ret != 0)
+               goto out;
+
+       if (decrypt)
+               ret = crypto_blkcipher_decrypt_iv(&desc, &sg, &sg, length);
+       else
+               ret = crypto_blkcipher_encrypt_iv(&desc, &sg, &sg, length);
+
+       gss_teardown_sgtable(&sg_out);
+out:
+       return ret;
+}
+
+int gss_digest_hmac(struct crypto_hash *tfm,
+                   rawobj_t *key,
+                   rawobj_t *hdr,
+                   int msgcnt, rawobj_t *msgs,
+                   int iovcnt, lnet_kiov_t *iovs,
+                   rawobj_t *cksum)
+{
+       struct hash_desc desc = {
+               .tfm = tfm,
+               .flags = 0,
+       };
+       struct scatterlist sg[1];
+       struct sg_table sgt;
+       int i;
+       int rc;
+
+       rc = crypto_hash_setkey(tfm, key->data, key->len);
+       if (rc)
+               return rc;
+
+       rc = crypto_hash_init(&desc);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < msgcnt; i++) {
+               if (msgs[i].len == 0)
+                       continue;
+
+               rc = gss_setup_sgtable(&sgt, sg, msgs[i].data, msgs[i].len);
+               if (rc != 0)
+                       return rc;
+               rc = crypto_hash_update(&desc, sg, msgs[i].len);
+               if (rc)
+                       return rc;
+
+               gss_teardown_sgtable(&sgt);
+       }
+
+       for (i = 0; i < iovcnt; i++) {
+               if (iovs[i].kiov_len == 0)
+                       continue;
+
+               sg_init_table(sg, 1);
+               sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
+                           iovs[i].kiov_offset);
+               rc = crypto_hash_update(&desc, sg, iovs[i].kiov_len);
+               if (rc)
+                       return rc;
+       }
+
+       if (hdr) {
+               rc = gss_setup_sgtable(&sgt, sg, (char *)hdr, sizeof(*hdr));
+               if (rc != 0)
+                       return rc;
+               rc = crypto_hash_update(&desc, sg, sizeof(hdr->len));
+               if (rc)
+                       return rc;
+
+               gss_teardown_sgtable(&sgt);
+       }
+
+       return crypto_hash_final(&desc, cksum->data);
+}
+
+int gss_digest_norm(struct crypto_hash *tfm,
+                   struct gss_keyblock *kb,
+                   rawobj_t *hdr,
+                   int msgcnt, rawobj_t *msgs,
+                   int iovcnt, lnet_kiov_t *iovs,
+                   rawobj_t *cksum)
+{
+       struct hash_desc   desc;
+       struct scatterlist sg[1];
+       struct sg_table sgt;
+       int                i;
+       int                rc;
+
+       LASSERT(kb->kb_tfm);
+       desc.tfm = tfm;
+       desc.flags = 0;
+
+       rc = crypto_hash_init(&desc);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < msgcnt; i++) {
+               if (msgs[i].len == 0)
+                       continue;
+
+               rc = gss_setup_sgtable(&sgt, sg, msgs[i].data, msgs[i].len);
+               if (rc != 0)
+                       return rc;
+
+               rc = crypto_hash_update(&desc, sg, msgs[i].len);
+               if (rc)
+                       return rc;
+
+               gss_teardown_sgtable(&sgt);
+       }
+
+       for (i = 0; i < iovcnt; i++) {
+               if (iovs[i].kiov_len == 0)
+                       continue;
+
+               sg_init_table(sg, 1);
+               sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
+                           iovs[i].kiov_offset);
+               rc = crypto_hash_update(&desc, sg, iovs[i].kiov_len);
+               if (rc)
+                       return rc;
+       }
+
+       if (hdr) {
+               rc = gss_setup_sgtable(&sgt, sg, (char *)hdr, sizeof(*hdr));
+               if (rc != 0)
+                       return rc;
+
+               rc = crypto_hash_update(&desc, sg, sizeof(*hdr));
+               if (rc)
+                       return rc;
+
+               gss_teardown_sgtable(&sgt);
+       }
+
+       rc = crypto_hash_final(&desc, cksum->data);
+       if (rc)
+               return rc;
+
+       return gss_crypt_generic(kb->kb_tfm, 0, NULL, cksum->data,
+                                cksum->data, cksum->len);
+}
+
+int gss_add_padding(rawobj_t *msg, int msg_buflen, int blocksize)
+{
+       int padding;
+
+       padding = (blocksize - (msg->len & (blocksize - 1))) &
+                 (blocksize - 1);
+       if (!padding)
+               return 0;
+
+       if (msg->len + padding > msg_buflen) {
+               CERROR("bufsize %u too small: datalen %u, padding %u\n",
+                      msg_buflen, msg->len, padding);
+               return -EINVAL;
+       }
+
+       memset(msg->data + msg->len, padding, padding);
+       msg->len += padding;
+       return 0;
+}
+
+int gss_crypt_rawobjs(struct crypto_blkcipher *tfm,
+                     int use_internal_iv,
+                     int inobj_cnt,
+                     rawobj_t *inobjs,
+                     rawobj_t *outobj,
+                     int enc)
+{
+       struct blkcipher_desc desc;
+       struct scatterlist src;
+       struct scatterlist dst;
+       struct sg_table sg_dst;
+       struct sg_table sg_src;
+       __u8 local_iv[16] = {0}, *buf;
+       __u32 datalen = 0;
+       int i, rc;
+       ENTRY;
+
+       buf = outobj->data;
+       desc.tfm  = tfm;
+       desc.info = local_iv;
+       desc.flags = 0;
+
+       for (i = 0; i < inobj_cnt; i++) {
+               LASSERT(buf + inobjs[i].len <= outobj->data + outobj->len);
+
+               rc = gss_setup_sgtable(&sg_src, &src, inobjs[i].data,
+                                  inobjs[i].len);
+               if (rc != 0)
+                       RETURN(rc);
+
+               rc = gss_setup_sgtable(&sg_dst, &dst, buf,
+                                      outobj->len - datalen);
+               if (rc != 0) {
+                       gss_teardown_sgtable(&sg_src);
+                       RETURN(rc);
+               }
+
+               if (use_internal_iv) {
+                       if (enc)
+                               rc = crypto_blkcipher_encrypt(&desc, &dst, &src,
+                                                             src.length);
+                       else
+                               rc = crypto_blkcipher_decrypt(&desc, &dst, &src,
+                                                             src.length);
+               } else {
+                       if (enc)
+                               rc = crypto_blkcipher_encrypt_iv(&desc, &dst,
+                                                                &src,
+                                                                src.length);
+                       else
+                               rc = crypto_blkcipher_decrypt_iv(&desc, &dst,
+                                                                &src,
+                                                                src.length);
+               }
+
+               gss_teardown_sgtable(&sg_src);
+               gss_teardown_sgtable(&sg_dst);
+
+               if (rc) {
+                       CERROR("encrypt error %d\n", rc);
+                       RETURN(rc);
+               }
+
+               datalen += inobjs[i].len;
+               buf += inobjs[i].len;
+       }
+
+       outobj->len = datalen;
+       RETURN(0);
+}
diff --git a/lustre/ptlrpc/gss/gss_crypto.h b/lustre/ptlrpc/gss/gss_crypto.h
new file mode 100644 (file)
index 0000000..91d1a4b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Modifications for Lustre
+ *
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Author: Eric Mei <ericm@clusterfs.com>
+ */
+
+/*
+ *  linux/include/linux/sunrpc/gss_krb5_types.h
+ *
+ *  Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
+ *  lib/gssapi/krb5/gssapiP_krb5.h, and others
+ *
+ *  Copyright (c) 2000 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson   <andros@umich.edu>
+ *  Bruce Fields   <bfields@umich.edu>
+ */
+
+/*
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#ifndef PTLRPC_GSS_UTILS_H
+#define PTLRPC_GSS_UTILS_H
+
+#include "gss_internal.h"
+
+struct gss_keyblock {
+       rawobj_t                 kb_key;
+       struct crypto_blkcipher *kb_tfm;
+};
+
+int gss_keyblock_init(struct gss_keyblock *kb, char *alg_name,
+                     const int alg_mode);
+void gss_keyblock_free(struct gss_keyblock *kb);
+int gss_keyblock_dup(struct gss_keyblock *new, struct gss_keyblock *kb);
+int gss_get_bytes(char **ptr, const char *end, void *res, size_t len);
+int gss_get_rawobj(char **ptr, const char *end, rawobj_t *res);
+int gss_get_keyblock(char **ptr, const char *end, struct gss_keyblock *kb,
+                    __u32 keysize);
+int gss_setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg,
+                     const void *buf, unsigned int buf_len);
+void gss_teardown_sgtable(struct sg_table *sgt);
+int gss_crypt_generic(struct crypto_blkcipher *tfm, int decrypt, void *iv,
+                       void *in, void *out, int length);
+int gss_digest_hmac(struct crypto_hash *tfm, rawobj_t *key, rawobj_t *hdr,
+                   int msgcnt, rawobj_t *msgs, int iovcnt, lnet_kiov_t *iovs,
+                   rawobj_t *cksum);
+int gss_digest_norm(struct crypto_hash *tfm, struct gss_keyblock *kb,
+                   rawobj_t *hdr, int msgcnt, rawobj_t *msgs, int iovcnt,
+                   lnet_kiov_t *iovs, rawobj_t *cksum);
+int gss_add_padding(rawobj_t *msg, int msg_buflen, int blocksize);
+int gss_crypt_rawobjs(struct crypto_blkcipher *tfm, int use_internal_iv,
+                     int inobj_cnt, rawobj_t *inobjs, rawobj_t *outobj,
+                     int enc);
+
+#endif /* PTLRPC_GSS_UTILS_H */
index 690704e..0c95d8d 100644 (file)
@@ -92,7 +92,11 @@ unsigned long gss_round_ctx_expiry(unsigned long expiry,
 /*
  * XXX make it visible of kernel and lgssd/lsvcgssd
  */
-#define GSSD_INTERFACE_VERSION          (1)
+enum {
+       GSSD_INTERFACE_VERSION_V1 = 1,
+       GSSD_INTERFACE_VERSION_V2 = 2,
+       GSSD_INTERFACE_VERSION = GSSD_INTERFACE_VERSION_V2,
+};
 
 #define PTLRPC_GSS_VERSION              (1)
 
index e8fbe50..1c28ede 100644 (file)
@@ -726,7 +726,8 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
         char                     desc[24];
         char                    *coinfo;
         int                      coinfo_size;
-        char                    *co_flags = "";
+       const char              *sec_part_flags = "";
+       char                     svc_flag = '\0';
         ENTRY;
 
         LASSERT(imp != NULL);
@@ -759,34 +760,51 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
                 /* update reverse handle for root user */
                 sec2gsec(sec)->gs_rvs_hdl = gss_get_next_ctx_index();
 
-                switch (sec->ps_part) {
-                case LUSTRE_SP_MDT:
-                        co_flags = "m";
-                        break;
-                case LUSTRE_SP_OST:
-                        co_flags = "o";
-                        break;
-                case LUSTRE_SP_MGC:
-                        co_flags = "rmo";
-                        break;
-                case LUSTRE_SP_CLI:
-                        co_flags = "r";
-                        break;
-                case LUSTRE_SP_MGS:
-                default:
-                        LBUG();
+               switch (sec->ps_part) {
+               case LUSTRE_SP_MDT:
+                       sec_part_flags = "m";
+                       break;
+               case LUSTRE_SP_OST:
+                       sec_part_flags = "o";
+                       break;
+               case LUSTRE_SP_MGC:
+                       sec_part_flags = "rmo";
+                       break;
+               case LUSTRE_SP_CLI:
+                       sec_part_flags = "r";
+                       break;
+               case LUSTRE_SP_MGS:
+               default:
+                       LBUG();
                 }
-        }
 
-        /* in case of setuid, key will be constructed as owner of fsuid/fsgid,
-         * but we do authentication based on real uid/gid. the key permission
-         * bits will be exactly as POS_ALL, so only processes who subscribed
-         * this key could have the access, although the quota might be counted
-         * on others (fsuid/fsgid).
-         *
-         * keyring will use fsuid/fsgid as upcall parameters, so we have to
-         * encode real uid/gid into callout info.
-         */
+               switch (SPTLRPC_FLVR_SVC(sec->ps_flvr.sf_rpc)) {
+               case SPTLRPC_SVC_NULL:
+                       svc_flag = 'n';
+                       break;
+               case SPTLRPC_SVC_AUTH:
+                       svc_flag = 'a';
+                       break;
+               case SPTLRPC_SVC_INTG:
+                       svc_flag = 'i';
+                       break;
+               case SPTLRPC_SVC_PRIV:
+                       svc_flag = 'p';
+                       break;
+               default:
+                       LBUG();
+               }
+       }
+
+       /* in case of setuid, key will be constructed as owner of fsuid/fsgid,
+        * but we do authentication based on real uid/gid. the key permission
+        * bits will be exactly as POS_ALL, so only processes who subscribed
+        * this key could have the access, although the quota might be counted
+        * on others (fsuid/fsgid).
+        *
+        * keyring will use fsuid/fsgid as upcall parameters, so we have to
+        * encode real uid/gid into callout info.
+        */
 
        /* But first we need to make sure the obd type is supported */
        if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
@@ -795,24 +813,24 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
            strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_LWP_NAME) &&
            strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSP_NAME)) {
                CERROR("obd %s is not a supported device\n",
-                       imp->imp_obd->obd_name);
+                      imp->imp_obd->obd_name);
                GOTO(out, ctx = NULL);
        }
 
-        construct_key_desc(desc, sizeof(desc), sec, vcred->vc_uid);
+       construct_key_desc(desc, sizeof(desc), sec, vcred->vc_uid);
 
-        /* callout info format:
-         * secid:mech:uid:gid:flags:svc_type:peer_nid:target_uuid
-         */
+       /* callout info format:
+        * secid:mech:uid:gid:sec_flags:svc_flag:svc_type:peer_nid:target_uuid
+        */
         coinfo_size = sizeof(struct obd_uuid) + MAX_OBD_NAME + 64;
         OBD_ALLOC(coinfo, coinfo_size);
         if (coinfo == NULL)
                 goto out;
 
-       snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%d:"LPX64":%s:"LPX64,
+       snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%c:%d:"LPX64":%s:"LPX64,
                 sec->ps_id, sec2gsec(sec)->gs_mech->gm_name,
                 vcred->vc_uid, vcred->vc_gid,
-                co_flags, import_to_gss_svc(imp),
+                sec_part_flags, svc_flag, import_to_gss_svc(imp),
                 imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name,
                 imp->imp_connection->c_self);
 
@@ -1070,7 +1088,7 @@ int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq)
                         snprintf(mech, sizeof(mech), "N/A");
                 mech[sizeof(mech) - 1] = '\0';
 
-               seq_printf(seq, "%p: uid %u, ref %d, expire %ld(%+ld), fl %s, "
+               seq_printf(seq, "%p: uid %u, ref %d, expire %lu(%+ld), fl %s, "
                           "seq %d, win %u, key %08x(ref %d), "
                           "hdl "LPX64":"LPX64", mech: %s\n",
                           ctx, ctx->cc_vcred.vc_uid,
@@ -1382,49 +1400,49 @@ int gss_kt_update(struct key *key, const void *data, size_t datalen)
                 goto out;
         }
 
-        if (gctx->gc_win == 0) {
-                __u32   nego_rpc_err, nego_gss_err;
+       if (gctx->gc_win == 0) {
+               __u32   nego_rpc_err, nego_gss_err;
 
-                rc = buffer_extract_bytes(&data, &datalen32, &nego_rpc_err,
-                                          sizeof(nego_rpc_err));
-                if (rc) {
-                        CERROR("failed to extrace rpc rc\n");
-                        goto out;
-                }
+               rc = buffer_extract_bytes(&data, &datalen32, &nego_rpc_err,
+                                         sizeof(nego_rpc_err));
+               if (rc) {
+                       CERROR("cannot extract RPC: rc = %d\n", rc);
+                       goto out;
+               }
 
-                rc = buffer_extract_bytes(&data, &datalen32, &nego_gss_err,
-                                          sizeof(nego_gss_err));
-                if (rc) {
-                        CERROR("failed to extrace gss rc\n");
-                        goto out;
-                }
+               rc = buffer_extract_bytes(&data, &datalen32, &nego_gss_err,
+                                         sizeof(nego_gss_err));
+               if (rc) {
+                       CERROR("failed to extract gss rc = %d\n", rc);
+                       goto out;
+               }
 
-                CERROR("negotiation: rpc err %d, gss err %x\n",
-                       nego_rpc_err, nego_gss_err);
+               CERROR("negotiation: rpc err %d, gss err %x\n",
+                      nego_rpc_err, nego_gss_err);
 
-                rc = nego_rpc_err ? nego_rpc_err : -EACCES;
-        } else {
-                rc = rawobj_extract_local_alloc(&gctx->gc_handle,
-                                                (__u32 **) &data, &datalen32);
-                if (rc) {
-                        CERROR("failed extract handle\n");
-                        goto out;
-                }
+               rc = nego_rpc_err ? nego_rpc_err : -EACCES;
+       } else {
+               rc = rawobj_extract_local_alloc(&gctx->gc_handle,
+                                               (__u32 **) &data, &datalen32);
+               if (rc) {
+                       CERROR("failed extract handle\n");
+                       goto out;
+               }
 
-                rc = rawobj_extract_local(&tmpobj, (__u32 **) &data,&datalen32);
-                if (rc) {
-                        CERROR("failed extract mech\n");
-                        goto out;
-                }
+               rc = rawobj_extract_local(&tmpobj, (__u32 **) &data,&datalen32);
+               if (rc) {
+                       CERROR("failed extract mech\n");
+                       goto out;
+               }
 
-                rc = lgss_import_sec_context(&tmpobj,
-                                             sec2gsec(ctx->cc_sec)->gs_mech,
-                                             &gctx->gc_mechctx);
-                if (rc != GSS_S_COMPLETE)
-                        CERROR("failed import context\n");
-                else
-                        rc = 0;
-        }
+               rc = lgss_import_sec_context(&tmpobj,
+                                            sec2gsec(ctx->cc_sec)->gs_mech,
+                                            &gctx->gc_mechctx);
+               if (rc != GSS_S_COMPLETE)
+                       CERROR("failed import context\n");
+               else
+                       rc = 0;
+       }
 out:
         /* we don't care what current status of this ctx, even someone else
          * is operating on the ctx at the same time. we just add up our own
index 01edf15..97ad55e 100644 (file)
@@ -47,6 +47,8 @@
 #ifndef PTLRPC_GSS_KRB5_H
 #define PTLRPC_GSS_KRB5_H
 
+#include "gss_crypto.h"
+
 /*
  * RFC 4142
  */
@@ -73,25 +75,20 @@ struct krb5_header {
         __u8            kh_cksum[0];    /* checksum */
 };
 
-struct krb5_keyblock {
-       rawobj_t                 kb_key;
-       struct crypto_blkcipher *kb_tfm;
-};
-
 struct krb5_ctx {
-        unsigned int            kc_initiate:1,
-                                kc_cfx:1,
-                                kc_seed_init:1,
-                                kc_have_acceptor_subkey:1;
-        __s32                   kc_endtime;
-        __u8                    kc_seed[16];
-        __u64                   kc_seq_send;
-        __u64                   kc_seq_recv;
-        __u32                   kc_enctype;
-        struct krb5_keyblock    kc_keye;        /* encryption */
-        struct krb5_keyblock    kc_keyi;        /* integrity */
-        struct krb5_keyblock    kc_keyc;        /* checksum */
-        rawobj_t                kc_mech_used;
+       unsigned int            kc_initiate:1,
+                               kc_cfx:1,
+                               kc_seed_init:1,
+                               kc_have_acceptor_subkey:1;
+       __s32                   kc_endtime;
+       __u8                    kc_seed[16];
+       __u64                   kc_seq_send;
+       __u64                   kc_seq_recv;
+       __u32                   kc_enctype;
+       struct gss_keyblock     kc_keye;        /* encryption */
+       struct gss_keyblock     kc_keyi;        /* integrity */
+       struct gss_keyblock     kc_keyc;        /* checksum */
+       rawobj_t                kc_mech_used;
 };
 
 enum sgn_alg {
index 289ab08..acb6308 100644 (file)
@@ -68,6 +68,7 @@
 #include "gss_api.h"
 #include "gss_asn1.h"
 #include "gss_krb5.h"
+#include "gss_crypto.h"
 
 static spinlock_t krb5_seq_lock;
 
@@ -145,25 +146,6 @@ static const char * enctype2str(__u32 enctype)
 }
 
 static
-int keyblock_init(struct krb5_keyblock *kb, char *alg_name, int alg_mode)
-{
-       kb->kb_tfm = crypto_alloc_blkcipher(alg_name, alg_mode, 0);
-       if (IS_ERR(kb->kb_tfm)) {
-               CERROR("failed to alloc tfm: %s, mode %d\n",
-                      alg_name, alg_mode);
-               return -1;
-       }
-
-       if (crypto_blkcipher_setkey(kb->kb_tfm, kb->kb_key.data, kb->kb_key.len)) {
-                CERROR("failed to set %s key, len %d\n",
-                       alg_name, kb->kb_key.len);
-                return -1;
-        }
-
-        return 0;
-}
-
-static
 int krb5_init_keys(struct krb5_ctx *kctx)
 {
         struct krb5_enctype *ke;
@@ -176,175 +158,104 @@ int krb5_init_keys(struct krb5_ctx *kctx)
 
         ke = &enctypes[kctx->kc_enctype];
 
-        /* tfm arc4 is stateful, user should alloc-use-free by his own */
-        if (kctx->kc_enctype != ENCTYPE_ARCFOUR_HMAC &&
-            keyblock_init(&kctx->kc_keye, ke->ke_enc_name, ke->ke_enc_mode))
-                return -1;
-
-        /* tfm hmac is stateful, user should alloc-use-free by his own */
-        if (ke->ke_hash_hmac == 0 &&
-            keyblock_init(&kctx->kc_keyi, ke->ke_enc_name, ke->ke_enc_mode))
-                return -1;
-        if (ke->ke_hash_hmac == 0 &&
-            keyblock_init(&kctx->kc_keyc, ke->ke_enc_name, ke->ke_enc_mode))
-                return -1;
-
-        return 0;
-}
-
-static
-void keyblock_free(struct krb5_keyblock *kb)
-{
-        rawobj_free(&kb->kb_key);
-        if (kb->kb_tfm)
-               crypto_free_blkcipher(kb->kb_tfm);
-}
-
-static
-int keyblock_dup(struct krb5_keyblock *new, struct krb5_keyblock *kb)
-{
-        return rawobj_dup(&new->kb_key, &kb->kb_key);
-}
-
-static
-int get_bytes(char **ptr, const char *end, void *res, int len)
-{
-        char *p, *q;
-        p = *ptr;
-        q = p + len;
-        if (q > end || q < p)
-                return -1;
-        memcpy(res, p, len);
-        *ptr = q;
-        return 0;
-}
-
-static
-int get_rawobj(char **ptr, const char *end, rawobj_t *res)
-{
-        char   *p, *q;
-        __u32   len;
-
-        p = *ptr;
-        if (get_bytes(&p, end, &len, sizeof(len)))
-                return -1;
-
-        q = p + len;
-        if (q > end || q < p)
-                return -1;
-
-        OBD_ALLOC_LARGE(res->data, len);
-        if (!res->data)
-                return -1;
-
-        res->len = len;
-        memcpy(res->data, p, len);
-        *ptr = q;
-        return 0;
-}
-
-static
-int get_keyblock(char **ptr, const char *end,
-                 struct krb5_keyblock *kb, __u32 keysize)
-{
-        char *buf;
-
-        OBD_ALLOC_LARGE(buf, keysize);
-        if (buf == NULL)
-                return -1;
+       /* tfm arc4 is stateful, user should alloc-use-free by his own */
+       if (kctx->kc_enctype != ENCTYPE_ARCFOUR_HMAC &&
+           gss_keyblock_init(&kctx->kc_keye, ke->ke_enc_name, ke->ke_enc_mode))
+               return -1;
 
-        if (get_bytes(ptr, end, buf, keysize)) {
-                OBD_FREE_LARGE(buf, keysize);
-                return -1;
-        }
+       /* tfm hmac is stateful, user should alloc-use-free by his own */
+       if (ke->ke_hash_hmac == 0 &&
+           gss_keyblock_init(&kctx->kc_keyi, ke->ke_enc_name, ke->ke_enc_mode))
+               return -1;
+       if (ke->ke_hash_hmac == 0 &&
+           gss_keyblock_init(&kctx->kc_keyc, ke->ke_enc_name, ke->ke_enc_mode))
+               return -1;
 
-        kb->kb_key.len = keysize;
-        kb->kb_key.data = buf;
         return 0;
 }
 
 static
 void delete_context_kerberos(struct krb5_ctx *kctx)
 {
-        rawobj_free(&kctx->kc_mech_used);
+       rawobj_free(&kctx->kc_mech_used);
 
-        keyblock_free(&kctx->kc_keye);
-        keyblock_free(&kctx->kc_keyi);
-        keyblock_free(&kctx->kc_keyc);
+       gss_keyblock_free(&kctx->kc_keye);
+       gss_keyblock_free(&kctx->kc_keyi);
+       gss_keyblock_free(&kctx->kc_keyc);
 }
 
 static
 __u32 import_context_rfc1964(struct krb5_ctx *kctx, char *p, char *end)
 {
-        unsigned int    tmp_uint, keysize;
+       unsigned int    tmp_uint, keysize;
 
-        /* seed_init flag */
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-                goto out_err;
-        kctx->kc_seed_init = (tmp_uint != 0);
+       /* seed_init flag */
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
+               goto out_err;
+       kctx->kc_seed_init = (tmp_uint != 0);
 
-        /* seed */
-        if (get_bytes(&p, end, kctx->kc_seed, sizeof(kctx->kc_seed)))
-                goto out_err;
+       /* seed */
+       if (gss_get_bytes(&p, end, kctx->kc_seed, sizeof(kctx->kc_seed)))
+               goto out_err;
 
-        /* sign/seal algorithm, not really used now */
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
-            get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-                goto out_err;
+       /* sign/seal algorithm, not really used now */
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
+           gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
+               goto out_err;
 
-        /* end time */
-        if (get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
-                goto out_err;
+       /* end time */
+       if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
+               goto out_err;
 
-        /* seq send */
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-                goto out_err;
-        kctx->kc_seq_send = tmp_uint;
+       /* seq send */
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
+               goto out_err;
+       kctx->kc_seq_send = tmp_uint;
 
-        /* mech oid */
-        if (get_rawobj(&p, end, &kctx->kc_mech_used))
-                goto out_err;
+       /* mech oid */
+       if (gss_get_rawobj(&p, end, &kctx->kc_mech_used))
+               goto out_err;
 
-        /* old style enc/seq keys in format:
-         *   - enctype (u32)
-         *   - keysize (u32)
-         *   - keydata
-         * we decompose them to fit into the new context
-         */
+       /* old style enc/seq keys in format:
+        *   - enctype (u32)
+        *   - keysize (u32)
+        *   - keydata
+        * we decompose them to fit into the new context
+        */
 
-        /* enc key */
-        if (get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
-                goto out_err;
+       /* enc key */
+       if (gss_get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
+               goto out_err;
 
-        if (get_bytes(&p, end, &keysize, sizeof(keysize)))
-                goto out_err;
+       if (gss_get_bytes(&p, end, &keysize, sizeof(keysize)))
+               goto out_err;
 
-        if (get_keyblock(&p, end, &kctx->kc_keye, keysize))
-                goto out_err;
+       if (gss_get_keyblock(&p, end, &kctx->kc_keye, keysize))
+               goto out_err;
 
-        /* seq key */
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
-            tmp_uint != kctx->kc_enctype)
-                goto out_err;
+       /* seq key */
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
+           tmp_uint != kctx->kc_enctype)
+               goto out_err;
 
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
-            tmp_uint != keysize)
-                goto out_err;
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)) ||
+           tmp_uint != keysize)
+               goto out_err;
 
-        if (get_keyblock(&p, end, &kctx->kc_keyc, keysize))
-                goto out_err;
+       if (gss_get_keyblock(&p, end, &kctx->kc_keyc, keysize))
+               goto out_err;
 
-        /* old style fallback */
-        if (keyblock_dup(&kctx->kc_keyi, &kctx->kc_keyc))
-                goto out_err;
+       /* old style fallback */
+       if (gss_keyblock_dup(&kctx->kc_keyi, &kctx->kc_keyc))
+               goto out_err;
 
-        if (p != end)
-                goto out_err;
+       if (p != end)
+               goto out_err;
 
        CDEBUG(D_SEC, "successfully imported rfc1964 context\n");
-        return 0;
+       return 0;
 out_err:
-        return GSS_S_FAILURE;
+       return GSS_S_FAILURE;
 }
 
 /* Flags for version 2 context flags */
@@ -355,58 +266,59 @@ out_err:
 static
 __u32 import_context_rfc4121(struct krb5_ctx *kctx, char *p, char *end)
 {
-        unsigned int    tmp_uint, keysize;
-
-        /* end time */
-        if (get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
-                goto out_err;
-
-        /* flags */
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-                goto out_err;
-
-        if (tmp_uint & KRB5_CTX_FLAG_INITIATOR)
-                kctx->kc_initiate = 1;
-        if (tmp_uint & KRB5_CTX_FLAG_CFX)
-                kctx->kc_cfx = 1;
-        if (tmp_uint & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
-                kctx->kc_have_acceptor_subkey = 1;
-
-        /* seq send */
-        if (get_bytes(&p, end, &kctx->kc_seq_send, sizeof(kctx->kc_seq_send)))
-                goto out_err;
-
-        /* enctype */
-        if (get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
-                goto out_err;
-
-        /* size of each key */
-        if (get_bytes(&p, end, &keysize, sizeof(keysize)))
-                goto out_err;
-
-        /* number of keys - should always be 3 */
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
-                goto out_err;
-
-        if (tmp_uint != 3) {
-                CERROR("Invalid number of keys: %u\n", tmp_uint);
-                goto out_err;
-        }
+       unsigned int    tmp_uint, keysize;
+
+       /* end time */
+       if (gss_get_bytes(&p, end, &kctx->kc_endtime, sizeof(kctx->kc_endtime)))
+               goto out_err;
+
+       /* flags */
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
+               goto out_err;
+
+       if (tmp_uint & KRB5_CTX_FLAG_INITIATOR)
+               kctx->kc_initiate = 1;
+       if (tmp_uint & KRB5_CTX_FLAG_CFX)
+               kctx->kc_cfx = 1;
+       if (tmp_uint & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
+               kctx->kc_have_acceptor_subkey = 1;
+
+       /* seq send */
+       if (gss_get_bytes(&p, end, &kctx->kc_seq_send,
+           sizeof(kctx->kc_seq_send)))
+               goto out_err;
+
+       /* enctype */
+       if (gss_get_bytes(&p, end, &kctx->kc_enctype, sizeof(kctx->kc_enctype)))
+               goto out_err;
+
+       /* size of each key */
+       if (gss_get_bytes(&p, end, &keysize, sizeof(keysize)))
+               goto out_err;
+
+       /* number of keys - should always be 3 */
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint)))
+               goto out_err;
+
+       if (tmp_uint != 3) {
+               CERROR("Invalid number of keys: %u\n", tmp_uint);
+               goto out_err;
+       }
 
-        /* ke */
-        if (get_keyblock(&p, end, &kctx->kc_keye, keysize))
-                goto out_err;
-        /* ki */
-        if (get_keyblock(&p, end, &kctx->kc_keyi, keysize))
-                goto out_err;
-        /* ki */
-        if (get_keyblock(&p, end, &kctx->kc_keyc, keysize))
-                goto out_err;
+       /* ke */
+       if (gss_get_keyblock(&p, end, &kctx->kc_keye, keysize))
+               goto out_err;
+       /* ki */
+       if (gss_get_keyblock(&p, end, &kctx->kc_keyi, keysize))
+               goto out_err;
+       /* ki */
+       if (gss_get_keyblock(&p, end, &kctx->kc_keyc, keysize))
+               goto out_err;
 
        CDEBUG(D_SEC, "successfully imported v2 context\n");
-        return 0;
+       return 0;
 out_err:
-        return GSS_S_FAILURE;
+       return GSS_S_FAILURE;
 }
 
 /*
@@ -418,15 +330,15 @@ static
 __u32 gss_import_sec_context_kerberos(rawobj_t *inbuf,
                                       struct gss_ctx *gctx)
 {
-        struct krb5_ctx *kctx;
-        char            *p = (char *) inbuf->data;
-        char            *end = (char *) (inbuf->data + inbuf->len);
-        unsigned int     tmp_uint, rc;
+       struct krb5_ctx *kctx;
+       char *p = (char *)inbuf->data;
+       char *end = (char *)(inbuf->data + inbuf->len);
+       unsigned int tmp_uint, rc;
 
-        if (get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) {
-                CERROR("Fail to read version\n");
-                return GSS_S_FAILURE;
-        }
+       if (gss_get_bytes(&p, end, &tmp_uint, sizeof(tmp_uint))) {
+               CERROR("Fail to read version\n");
+               return GSS_S_FAILURE;
+       }
 
         /* only support 0, 1 for the moment */
         if (tmp_uint > 2) {
@@ -484,12 +396,12 @@ __u32 gss_copy_reverse_context_kerberos(struct gss_ctx *gctx,
         if (rawobj_dup(&knew->kc_mech_used, &kctx->kc_mech_used))
                 goto out_err;
 
-        if (keyblock_dup(&knew->kc_keye, &kctx->kc_keye))
-                goto out_err;
-        if (keyblock_dup(&knew->kc_keyi, &kctx->kc_keyi))
-                goto out_err;
-        if (keyblock_dup(&knew->kc_keyc, &kctx->kc_keyc))
-                goto out_err;
+       if (gss_keyblock_dup(&knew->kc_keye, &kctx->kc_keye))
+               goto out_err;
+       if (gss_keyblock_dup(&knew->kc_keyi, &kctx->kc_keyi))
+               goto out_err;
+       if (gss_keyblock_dup(&knew->kc_keyc, &kctx->kc_keyc))
+               goto out_err;
         if (krb5_init_keys(knew))
                 goto out_err;
 
@@ -509,7 +421,7 @@ __u32 gss_inquire_context_kerberos(struct gss_ctx *gctx,
 {
         struct krb5_ctx *kctx = gctx->internal_ctx_id;
 
-        *endtime = (unsigned long) ((__u32) kctx->kc_endtime);
+       *endtime = (unsigned long)((__u32) kctx->kc_endtime);
         return GSS_S_COMPLETE;
 }
 
@@ -523,254 +435,20 @@ void gss_delete_sec_context_kerberos(void *internal_ctx)
 }
 
 /*
- * Should be used for buffers allocated with k/vmalloc().
- *
- * Dispose of @sgt with teardown_sgtable().
- *
- * @prealloc_sg is to avoid memory allocation inside sg_alloc_table()
- * in cases where a single sg is sufficient.  No attempt to reduce the
- * number of sgs by squeezing physically contiguous pages together is
- * made though, for simplicity.
- *
- * This function is copied from the ceph filesystem code.
- */
-static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg,
-                        const void *buf, unsigned int buf_len)
-{
-       struct scatterlist *sg;
-       const bool is_vmalloc = is_vmalloc_addr(buf);
-       unsigned int off = offset_in_page(buf);
-       unsigned int chunk_cnt = 1;
-       unsigned int chunk_len = PAGE_ALIGN(off + buf_len);
-       int i;
-       int ret;
-
-       if (buf_len == 0) {
-               memset(sgt, 0, sizeof(*sgt));
-               return -EINVAL;
-       }
-
-       if (is_vmalloc) {
-               chunk_cnt = chunk_len >> PAGE_SHIFT;
-               chunk_len = PAGE_SIZE;
-       }
-
-       if (chunk_cnt > 1) {
-               ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS);
-               if (ret)
-                       return ret;
-       } else {
-               WARN_ON(chunk_cnt != 1);
-               sg_init_table(prealloc_sg, 1);
-               sgt->sgl = prealloc_sg;
-               sgt->nents = sgt->orig_nents = 1;
-       }
-
-       for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
-               struct page *page;
-               unsigned int len = min(chunk_len - off, buf_len);
-
-               if (is_vmalloc)
-                       page = vmalloc_to_page(buf);
-               else
-                       page = virt_to_page(buf);
-
-               sg_set_page(sg, page, len, off);
-
-               off = 0;
-               buf += len;
-               buf_len -= len;
-       }
-
-       WARN_ON(buf_len != 0);
-
-       return 0;
-}
-
-static void teardown_sgtable(struct sg_table *sgt)
-{
-       if (sgt->orig_nents > 1)
-               sg_free_table(sgt);
-}
-
-static
-__u32 krb5_encrypt(struct crypto_blkcipher *tfm,
-                   int decrypt,
-                   void * iv,
-                   void * in,
-                   void * out,
-                   int length)
-{
-       struct sg_table sg_out;
-        struct blkcipher_desc desc;
-        struct scatterlist    sg;
-        __u8 local_iv[16] = {0};
-        __u32 ret = -EINVAL;
-
-        LASSERT(tfm);
-        desc.tfm  = tfm;
-        desc.info = local_iv;
-        desc.flags= 0;
-
-       if (length % crypto_blkcipher_blocksize(tfm) != 0) {
-                CERROR("output length %d mismatch blocksize %d\n",
-                      length, crypto_blkcipher_blocksize(tfm));
-                goto out;
-        }
-
-       if (crypto_blkcipher_ivsize(tfm) > 16) {
-               CERROR("iv size too large %d\n", crypto_blkcipher_ivsize(tfm));
-               goto out;
-       }
-
-       if (iv)
-               memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm));
-
-       memcpy(out, in, length);
-
-       ret = setup_sgtable(&sg_out, &sg, out, length);
-       if (ret != 0)
-               goto out;
-
-        if (decrypt)
-               ret = crypto_blkcipher_decrypt_iv(&desc, sg_out.sgl,
-                                                 sg_out.sgl, length);
-        else
-               ret = crypto_blkcipher_encrypt_iv(&desc, sg_out.sgl,
-                                                 sg_out.sgl, length);
-
-       teardown_sgtable(&sg_out);
-out:
-       return ret;
-}
-
-static inline
-int krb5_digest_hmac(struct crypto_hash *tfm,
-                     rawobj_t *key,
-                     struct krb5_header *khdr,
-                     int msgcnt, rawobj_t *msgs,
-                     int iovcnt, lnet_kiov_t *iovs,
-                     rawobj_t *cksum)
-{
-       struct hash_desc        desc;
-       struct sg_table         sgt;
-       struct scatterlist      sg[1];
-       int                     i, rc;
-
-       crypto_hash_setkey(tfm, key->data, key->len);
-        desc.tfm  = tfm;
-        desc.flags= 0;
-
-       crypto_hash_init(&desc);
-
-        for (i = 0; i < msgcnt; i++) {
-                if (msgs[i].len == 0)
-                        continue;
-
-               rc = setup_sgtable(&sgt, sg, msgs[i].data, msgs[i].len);
-               if (rc != 0)
-                       return rc;
-
-               crypto_hash_update(&desc, sgt.sgl, msgs[i].len);
-
-               teardown_sgtable(&sgt);
-        }
-
-        for (i = 0; i < iovcnt; i++) {
-                if (iovs[i].kiov_len == 0)
-                        continue;
-
-               sg_init_table(sg, 1);
-               sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
-                           iovs[i].kiov_offset);
-               crypto_hash_update(&desc, sg, iovs[i].kiov_len);
-        }
-
-        if (khdr) {
-               rc = setup_sgtable(&sgt, sg, (char *) khdr, sizeof(*khdr));
-               if (rc != 0)
-                       return rc;
-
-               crypto_hash_update(&desc, sgt.sgl, sizeof(*khdr));
-
-               teardown_sgtable(&sgt);
-        }
-
-       return crypto_hash_final(&desc, cksum->data);
-}
-
-static inline
-int krb5_digest_norm(struct crypto_hash *tfm,
-                     struct krb5_keyblock *kb,
-                     struct krb5_header *khdr,
-                     int msgcnt, rawobj_t *msgs,
-                     int iovcnt, lnet_kiov_t *iovs,
-                     rawobj_t *cksum)
-{
-       struct hash_desc        desc;
-       struct scatterlist      sg[1];
-       struct sg_table         sgt;
-       int                     i, rc;
-
-        LASSERT(kb->kb_tfm);
-        desc.tfm  = tfm;
-        desc.flags= 0;
-
-       crypto_hash_init(&desc);
-
-        for (i = 0; i < msgcnt; i++) {
-                if (msgs[i].len == 0)
-                        continue;
-
-               rc = setup_sgtable(&sgt, sg, msgs[i].data, msgs[i].len);
-               if (rc != 0)
-                       return rc;
-
-               crypto_hash_update(&desc, sgt.sgl, msgs[i].len);
-
-               teardown_sgtable(&sgt);
-        }
-
-        for (i = 0; i < iovcnt; i++) {
-                if (iovs[i].kiov_len == 0)
-                        continue;
-
-               sg_init_table(sg, 1);
-               sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
-                           iovs[i].kiov_offset);
-               crypto_hash_update(&desc, sg, iovs[i].kiov_len);
-        }
-
-        if (khdr) {
-               rc = setup_sgtable(&sgt, sg, (char *) khdr, sizeof(*khdr));
-               if (rc != 0)
-                       return rc;
-
-               crypto_hash_update(&desc, sgt.sgl, sizeof(*khdr));
-
-               teardown_sgtable(&sgt);
-       }
-
-       crypto_hash_final(&desc, cksum->data);
-
-        return krb5_encrypt(kb->kb_tfm, 0, NULL, cksum->data,
-                            cksum->data, cksum->len);
-}
-
-/*
  * compute (keyed/keyless) checksum against the plain text which appended
  * with krb5 wire token header.
  */
 static
 __s32 krb5_make_checksum(__u32 enctype,
-                         struct krb5_keyblock *kb,
-                         struct krb5_header *khdr,
-                         int msgcnt, rawobj_t *msgs,
-                         int iovcnt, lnet_kiov_t *iovs,
-                         rawobj_t *cksum)
+                        struct gss_keyblock *kb,
+                        struct krb5_header *khdr,
+                        int msgcnt, rawobj_t *msgs,
+                        int iovcnt, lnet_kiov_t *iovs,
+                        rawobj_t *cksum)
 {
         struct krb5_enctype   *ke = &enctypes[enctype];
        struct crypto_hash    *tfm;
+       rawobj_t               hdr;
         __u32                  code = GSS_S_FAILURE;
         int                    rc;
 
@@ -786,12 +464,15 @@ __s32 krb5_make_checksum(__u32 enctype,
                 goto out_tfm;
         }
 
+       hdr.data = (__u8 *)khdr;
+       hdr.len = sizeof(*khdr);
+
         if (ke->ke_hash_hmac)
-                rc = krb5_digest_hmac(tfm, &kb->kb_key,
-                                      khdr, msgcnt, msgs, iovcnt, iovs, cksum);
+               rc = gss_digest_hmac(tfm, &kb->kb_key,
+                                    &hdr, msgcnt, msgs, iovcnt, iovs, cksum);
         else
-                rc = krb5_digest_norm(tfm, kb,
-                                      khdr, msgcnt, msgs, iovcnt, iovs, cksum);
+               rc = gss_digest_norm(tfm, kb,
+                                    &hdr, msgcnt, msgs, iovcnt, iovs, cksum);
 
         if (rc == 0)
                 code = GSS_S_COMPLETE;
@@ -883,7 +564,7 @@ __u32 gss_get_mic_kerberos(struct gss_ctx *gctx,
 
         /* fill krb5 header */
         LASSERT(token->len >= sizeof(*khdr));
-        khdr = (struct krb5_header *) token->data;
+       khdr = (struct krb5_header *)token->data;
         fill_krb5_header(kctx, khdr, 0);
 
         /* checksum */
@@ -920,7 +601,7 @@ __u32 gss_verify_mic_kerberos(struct gss_ctx *gctx,
                 return GSS_S_DEFECTIVE_TOKEN;
         }
 
-        khdr = (struct krb5_header *) token->data;
+       khdr = (struct krb5_header *)token->data;
 
         major = verify_krb5_header(kctx, khdr, 0);
         if (major != GSS_S_COMPLETE) {
@@ -952,101 +633,6 @@ __u32 gss_verify_mic_kerberos(struct gss_ctx *gctx,
         return GSS_S_COMPLETE;
 }
 
-static
-int add_padding(rawobj_t *msg, int msg_buflen, int blocksize)
-{
-        int padding;
-
-        padding = (blocksize - (msg->len & (blocksize - 1))) &
-                  (blocksize - 1);
-        if (!padding)
-                return 0;
-
-        if (msg->len + padding > msg_buflen) {
-                CERROR("bufsize %u too small: datalen %u, padding %u\n",
-                        msg_buflen, msg->len, padding);
-                return -EINVAL;
-        }
-
-        memset(msg->data + msg->len, padding, padding);
-        msg->len += padding;
-        return 0;
-}
-
-static
-int krb5_encrypt_rawobjs(struct crypto_blkcipher *tfm,
-                         int mode_ecb,
-                         int inobj_cnt,
-                         rawobj_t *inobjs,
-                         rawobj_t *outobj,
-                         int enc)
-{
-        struct blkcipher_desc desc;
-        struct scatterlist    src, dst;
-       struct sg_table         sg_src, sg_dst;
-        __u8                  local_iv[16] = {0}, *buf;
-        __u32                 datalen = 0;
-        int                   i, rc;
-        ENTRY;
-
-        buf = outobj->data;
-        desc.tfm  = tfm;
-        desc.info = local_iv;
-        desc.flags = 0;
-
-        for (i = 0; i < inobj_cnt; i++) {
-               LASSERT(buf + inobjs[i].len <= outobj->data + outobj->len);
-
-               rc = setup_sgtable(&sg_src, &src, inobjs[i].data,
-                                  inobjs[i].len);
-               if (rc != 0)
-                       RETURN(rc);
-
-               rc = setup_sgtable(&sg_dst, &dst, buf,
-                                  outobj->len - datalen);
-               if (rc != 0) {
-                       teardown_sgtable(&sg_src);
-                       RETURN(rc);
-               }
-
-                if (mode_ecb) {
-                        if (enc)
-                               rc = crypto_blkcipher_encrypt(&desc, sg_dst.sgl,
-                                                             sg_src.sgl,
-                                                             inobjs[i].len);
-                        else
-                               rc = crypto_blkcipher_decrypt(&desc, sg_dst.sgl,
-                                                             sg_src.sgl,
-                                                             inobjs[i].len);
-                } else {
-                        if (enc)
-                               rc = crypto_blkcipher_encrypt_iv(&desc,
-                                                                sg_dst.sgl,
-                                                                sg_src.sgl,
-                                                                inobjs[i].len);
-                        else
-                               rc = crypto_blkcipher_decrypt_iv(&desc,
-                                                                sg_dst.sgl,
-                                                                sg_src.sgl,
-                                                                inobjs[i].len);
-                }
-
-               teardown_sgtable(&sg_src);
-               teardown_sgtable(&sg_dst);
-
-                if (rc) {
-                        CERROR("encrypt error %d\n", rc);
-                        RETURN(rc);
-                }
-
-                datalen += inobjs[i].len;
-                buf += inobjs[i].len;
-        }
-
-        outobj->len = datalen;
-        RETURN(0);
-}
-
 /*
  * if adj_nob != 0, we adjust desc->bd_nob to the actual cipher text size.
  */
@@ -1077,21 +663,21 @@ int krb5_encrypt_bulk(struct crypto_blkcipher *tfm,
         ciph_desc.flags = 0;
 
         /* encrypt confounder */
-       rc = setup_sgtable(&sg_src, &src, confounder, blocksize);
+       rc = gss_setup_sgtable(&sg_src, &src, confounder, blocksize);
        if (rc != 0)
                return rc;
 
-       rc = setup_sgtable(&sg_dst, &dst, cipher->data, blocksize);
+       rc = gss_setup_sgtable(&sg_dst, &dst, cipher->data, blocksize);
        if (rc != 0) {
-               teardown_sgtable(&sg_src);
+               gss_teardown_sgtable(&sg_src);
                return rc;
        }
 
        rc = crypto_blkcipher_encrypt_iv(&ciph_desc, sg_dst.sgl,
                                         sg_src.sgl, blocksize);
 
-       teardown_sgtable(&sg_dst);
-       teardown_sgtable(&sg_src);
+       gss_teardown_sgtable(&sg_dst);
+       gss_teardown_sgtable(&sg_src);
 
         if (rc) {
                 CERROR("error to encrypt confounder: %d\n", rc);
@@ -1124,22 +710,22 @@ int krb5_encrypt_bulk(struct crypto_blkcipher *tfm,
         }
 
         /* encrypt krb5 header */
-       rc = setup_sgtable(&sg_src, &src, khdr, sizeof(*khdr));
+       rc = gss_setup_sgtable(&sg_src, &src, khdr, sizeof(*khdr));
        if (rc != 0)
                return rc;
 
-       rc = setup_sgtable(&sg_dst, &dst, cipher->data + blocksize,
+       rc = gss_setup_sgtable(&sg_dst, &dst, cipher->data + blocksize,
                           sizeof(*khdr));
        if (rc != 0) {
-               teardown_sgtable(&sg_src);
+               gss_teardown_sgtable(&sg_src);
                return rc;
        }
 
        rc = crypto_blkcipher_encrypt_iv(&ciph_desc, sg_dst.sgl, sg_src.sgl,
                                         sizeof(*khdr));
 
-       teardown_sgtable(&sg_dst);
-       teardown_sgtable(&sg_src);
+       gss_teardown_sgtable(&sg_dst);
+       gss_teardown_sgtable(&sg_src);
 
         if (rc) {
                 CERROR("error to encrypt krb5 header: %d\n", rc);
@@ -1204,21 +790,21 @@ int krb5_decrypt_bulk(struct crypto_blkcipher *tfm,
         }
 
         /* decrypt head (confounder) */
-       rc = setup_sgtable(&sg_src, &src, cipher->data, blocksize);
+       rc = gss_setup_sgtable(&sg_src, &src, cipher->data, blocksize);
        if (rc != 0)
                return rc;
 
-       rc = setup_sgtable(&sg_dst, &dst, plain->data, blocksize);
+       rc = gss_setup_sgtable(&sg_dst, &dst, plain->data, blocksize);
        if (rc != 0) {
-               teardown_sgtable(&sg_src);
+               gss_teardown_sgtable(&sg_src);
                return rc;
        }
 
        rc = crypto_blkcipher_decrypt_iv(&ciph_desc, sg_dst.sgl,
                                         sg_src.sgl, blocksize);
 
-       teardown_sgtable(&sg_dst);
-       teardown_sgtable(&sg_src);
+       gss_teardown_sgtable(&sg_dst);
+       gss_teardown_sgtable(&sg_src);
 
         if (rc) {
                 CERROR("error to decrypt confounder: %d\n", rc);
@@ -1309,23 +895,23 @@ int krb5_decrypt_bulk(struct crypto_blkcipher *tfm,
                        BD_GET_KIOV(desc, i++).kiov_len = 0;
 
         /* decrypt tail (krb5 header) */
-       rc = setup_sgtable(&sg_src, &src, cipher->data + blocksize,
-                          sizeof(*khdr));
+       rc = gss_setup_sgtable(&sg_src, &src, cipher->data + blocksize,
+                              sizeof(*khdr));
        if (rc != 0)
                return rc;
 
-       rc = setup_sgtable(&sg_dst, &dst, cipher->data + blocksize,
-                          sizeof(*khdr));
+       rc = gss_setup_sgtable(&sg_dst, &dst, cipher->data + blocksize,
+                              sizeof(*khdr));
        if (rc != 0) {
-               teardown_sgtable(&sg_src);
+               gss_teardown_sgtable(&sg_src);
                return rc;
        }
 
        rc = crypto_blkcipher_decrypt_iv(&ciph_desc, sg_dst.sgl, sg_src.sgl,
                                         sizeof(*khdr));
 
-       teardown_sgtable(&sg_src);
-       teardown_sgtable(&sg_dst);
+       gss_teardown_sgtable(&sg_src);
+       gss_teardown_sgtable(&sg_dst);
 
         if (rc) {
                 CERROR("error to decrypt tail: %d\n", rc);
@@ -1371,7 +957,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
 
         /* fill krb5 header */
         LASSERT(token->len >= sizeof(*khdr));
-        khdr = (struct krb5_header *) token->data;
+       khdr = (struct krb5_header *)token->data;
         fill_krb5_header(kctx, khdr, 1);
 
         /* generate confounder */
@@ -1388,9 +974,9 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
         }
         LASSERT(blocksize <= ke->ke_conf_size);
 
-        /* padding the message */
-        if (add_padding(msg, msg_buflen, blocksize))
-                return GSS_S_FAILURE;
+       /* padding the message */
+       if (gss_add_padding(msg, msg_buflen, blocksize))
+               return GSS_S_FAILURE;
 
         /*
          * clear text layout for checksum:
@@ -1425,7 +1011,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
         data_desc[2].len = sizeof(*khdr);
 
         /* cipher text will be directly inplace */
-        cipher.data = (__u8 *) (khdr + 1);
+       cipher.data = (__u8 *)(khdr + 1);
         cipher.len = token->len - sizeof(*khdr);
         LASSERT(cipher.len >= ke->ke_conf_size + msg->len + sizeof(*khdr));
 
@@ -1452,8 +1038,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx,
                         GOTO(arc4_out_tfm, rc = -EACCES);
                 }
 
-                rc = krb5_encrypt_rawobjs(arc4_tfm, 1,
-                                          3, data_desc, &cipher, 1);
+               rc = gss_crypt_rawobjs(arc4_tfm, 1, 3, data_desc, &cipher, 1);
 arc4_out_tfm:
                crypto_free_blkcipher(arc4_tfm);
 arc4_out_key:
@@ -1461,8 +1046,8 @@ arc4_out_key:
 arc4_out:
                 do {} while(0); /* just to avoid compile warning */
         } else {
-                rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0,
-                                          3, data_desc, &cipher, 1);
+               rc = gss_crypt_rawobjs(kctx->kc_keye.kb_tfm, 0, 3, data_desc,
+                                      &cipher, 1);
         }
 
         if (rc != 0) {
@@ -1545,7 +1130,7 @@ __u32 gss_wrap_bulk_kerberos(struct gss_ctx *gctx,
 
         /* fill krb5 header */
         LASSERT(token->len >= sizeof(*khdr));
-        khdr = (struct krb5_header *) token->data;
+       khdr = (struct krb5_header *)token->data;
         fill_krb5_header(kctx, khdr, 1);
 
         /* generate confounder */
@@ -1602,7 +1187,7 @@ __u32 gss_wrap_bulk_kerberos(struct gss_ctx *gctx,
         data_desc[0].data = conf;
         data_desc[0].len = ke->ke_conf_size;
 
-        cipher.data = (__u8 *) (khdr + 1);
+       cipher.data = (__u8 *)(khdr + 1);
         cipher.len = blocksize + sizeof(*khdr);
 
         if (kctx->kc_enctype == ENCTYPE_ARCFOUR_HMAC) {
@@ -1654,7 +1239,7 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
                 return GSS_S_DEFECTIVE_TOKEN;
         }
 
-        khdr = (struct krb5_header *) token->data;
+       khdr = (struct krb5_header *)token->data;
 
         major = verify_krb5_header(kctx, khdr, 1);
         if (major != GSS_S_COMPLETE) {
@@ -1701,7 +1286,7 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
 
         major = GSS_S_FAILURE;
 
-        cipher_in.data = (__u8 *) (khdr + 1);
+       cipher_in.data = (__u8 *)(khdr + 1);
         cipher_in.len = bodysize;
         plain_out.data = tmpbuf;
         plain_out.len = bodysize;
@@ -1732,8 +1317,8 @@ __u32 gss_unwrap_kerberos(struct gss_ctx  *gctx,
                         GOTO(arc4_out_tfm, rc = -EACCES);
                 }
 
-                rc = krb5_encrypt_rawobjs(arc4_tfm, 1,
-                                          1, &cipher_in, &plain_out, 0);
+               rc = gss_crypt_rawobjs(arc4_tfm, 1, 1, &cipher_in,
+                                      &plain_out, 0);
 arc4_out_tfm:
                crypto_free_blkcipher(arc4_tfm);
 arc4_out_key:
@@ -1741,8 +1326,8 @@ arc4_out_key:
 arc4_out:
                 cksum = RAWOBJ_EMPTY;
         } else {
-                rc = krb5_encrypt_rawobjs(kctx->kc_keye.kb_tfm, 0,
-                                          1, &cipher_in, &plain_out, 0);
+               rc = gss_crypt_rawobjs(kctx->kc_keye.kb_tfm, 0, 1, &cipher_in,
+                                      &plain_out, 0);
         }
 
         if (rc != 0) {
@@ -1820,7 +1405,7 @@ __u32 gss_unwrap_bulk_kerberos(struct gss_ctx *gctx,
                 return GSS_S_DEFECTIVE_TOKEN;
         }
 
-        khdr = (struct krb5_header *) token->data;
+       khdr = (struct krb5_header *)token->data;
 
         major = verify_krb5_header(kctx, khdr, 1);
         if (major != GSS_S_COMPLETE) {
index 2786d69..8944ef8 100644 (file)
@@ -61,8 +61,9 @@
 #include <obd_class.h>
 #include <obd_support.h>
 #include <lustre/lustre_idl.h>
-#include <lustre_net.h>
 #include <lustre_import.h>
+#include <lustre_net.h>
+#include <lustre_nodemap.h>
 #include <lustre_sec.h>
 
 #include "gss_err.h"
@@ -132,7 +133,7 @@ static inline void _cache_unregister_net(struct cache_detail *cd,
 #endif
 }
 /****************************************
- * rsi cache                            *
+ * rpc sec init (rsi) cache *
  ****************************************/
 
 #define RSI_HASHBITS    (6)
@@ -143,6 +144,7 @@ struct rsi {
        struct cache_head       h;
        __u32                   lustre_svc;
        __u64                   nid;
+       char                    nm_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
        wait_queue_head_t       waitq;
        rawobj_t                in_handle, in_token;
        rawobj_t                out_handle, out_token;
@@ -180,6 +182,7 @@ static void rsi_free(struct rsi *rsi)
         rawobj_free(&rsi->out_token);
 }
 
+/* See handle_req() userspace for where the upcall data is read */
 static void rsi_request(struct cache_detail *cd,
                         struct cache_head *h,
                         char **bpp, int *blen)
@@ -195,6 +198,8 @@ static void rsi_request(struct cache_detail *cd,
                        sizeof(rsi->lustre_svc));
        qword_addhex(bpp, blen, (char *) &rsi->nid, sizeof(rsi->nid));
        qword_addhex(bpp, blen, (char *) &index, sizeof(index));
+       qword_addhex(bpp, blen, (char *) rsi->nm_name,
+                    strlen(rsi->nm_name) + 1);
        qword_addhex(bpp, blen, rsi->in_handle.data, rsi->in_handle.len);
        qword_addhex(bpp, blen, rsi->in_token.data, rsi->in_token.len);
        (*bpp)[-1] = '\n';
@@ -225,6 +230,7 @@ static inline void __rsi_init(struct rsi *new, struct rsi *item)
 
        new->lustre_svc = item->lustre_svc;
        new->nid = item->nid;
+       memcpy(new->nm_name, item->nm_name, sizeof(item->nm_name));
        init_waitqueue_head(&new->waitq);
 }
 
@@ -424,7 +430,7 @@ static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
 }
 
 /****************************************
- * rsc cache                            *
+ * rpc sec context (rsc) cache                            *
  ****************************************/
 
 #define RSC_HASHBITS    (10)
@@ -923,9 +929,11 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
        int                        rc = SECSVC_DROP;
        ENTRY;
 
-        memset(&rsikey, 0, sizeof(rsikey));
-        rsikey.lustre_svc = lustre_svc;
-        rsikey.nid = (__u64) req->rq_peer.nid;
+       memset(&rsikey, 0, sizeof(rsikey));
+       rsikey.lustre_svc = lustre_svc;
+       rsikey.nid = (__u64) req->rq_peer.nid;
+       nodemap_test_nid(req->rq_peer.nid, rsikey.nm_name,
+                        sizeof(rsikey.nm_name));
 
         /* duplicate context handle. for INIT it always 0 */
         if (rawobj_dup(&rsikey.in_handle, &gw->gw_handle)) {
index 87c3b80..03d6233 100755 (executable)
 . /etc/init.d/functions
 
 LOCKFILE="/var/lock/subsys/lsvcgssd"
+LSVCGSSDARGS="-k"
+
+# Check for and source configuration file
+[ -f /etc/sysconfig/lsvcgss ] && . /etc/sysconfig/lsvcgss
 
 # See how we were called.
 case "$1" in
        start)
                echo $"Starting lsvcgssd"
-               /usr/sbin/lsvcgssd
+               /usr/sbin/lsvcgssd ${LSVCGSSDARGS}
                RETVAL=$?
                [ $RETVAL -eq 0 ] && touch $LOCKFILE
                ;;
index 93eada7..bbb03d7 100644 (file)
@@ -58,7 +58,7 @@
 #include <errno.h>
 #include "err_util.h"
 
-void qword_add(char **bpp, int *lp, char *str)
+void qword_add(char **bpp, int *lp, const char *str)
 {
        char *bp = *bpp;
        int len = *lp;
@@ -154,7 +154,7 @@ void qword_addeol(char **bpp, int *lp)
 
 static char qword_buf[8192];
 static char tmp_buf[8192];
-int qword_print(FILE *f, char *str)
+int qword_print(FILE *f, const char *str)
 {
        char *bp = qword_buf;
        int len = sizeof(qword_buf);
index 4e2da47..365fcf1 100644 (file)
 
 #include <stdio.h>
 
-void qword_add(char **bpp, int *lp, char *str);
+void qword_add(char **bpp, int *lp, const char *str);
 void qword_addhex(char **bpp, int *lp, char *buf, int blen);
 void qword_addint(char **bpp, int *lp, int n);
 void qword_adduint(char **bpp, int *lp, unsigned int n);
 void qword_addeol(char **bpp, int *lp);
-int qword_print(FILE *f, char *str);
+int qword_print(FILE *f, const char *str);
 int qword_printhex(FILE *f, char *str, int slen);
 void qword_printint(FILE *f, int num);
 int qword_eol(FILE *f);
index fa457f5..76a172f 100644 (file)
@@ -97,11 +97,15 @@ printit:
 
 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");
+       print_hex(pri, cp, length);
+}
+
+void print_hex(int pri, unsigned char *cp, int length)
+{
+       int i, j, jm;
+       unsigned char c;
 
        for (i = 0; i < length; i += 0x10) {
                printerr(pri, "  %04x: ", (unsigned int)i);
index 7fff5ba..0070a3b 100644 (file)
@@ -35,5 +35,6 @@ void initerr(char *progname, int verbosity, int fg);
 void printerr(int priority, char *format, ...)
              __attribute__((__format__(__printf__, 2, 3)));
 void print_hexl(int pri, unsigned char *cp, int length);
+void print_hex(int pri, unsigned char *cp, int length);
 
 #endif /* _ERR_UTIL_H_ */
index 10768ca..2429f5c 100644 (file)
@@ -648,7 +648,7 @@ int do_negotiation(struct lustre_gss_data *lgd,
                return -1;
        }
 
-       param.version = GSSD_INTERFACE_VERSION;
+       param.version = GSSD_INTERFACE_VERSION_V1;
        param.uuid = lgd->lgd_uuid;
        param.lustre_svc = lgd->lgd_lustre_svc;
        param.uid = lgd->lgd_uid;
index c50f4b8..16e966e 100644 (file)
@@ -67,23 +67,24 @@ static char *g_service = NULL;
  * all data about negotiation
  */
 struct lgss_nego_data {
-       uint32_t        lnd_established:1;
-
-       int             lnd_secid;
-       uint32_t        lnd_uid;
-       uint32_t        lnd_lsvc;
-       char           *lnd_uuid;
-
-       gss_OID         lnd_mech;               /* mech OID */
-       gss_name_t      lnd_svc_name;           /* service name */
-       unsigned int    lnd_req_flags;          /* request flags */
-       gss_cred_id_t   lnd_cred;               /* credential */
-       gss_ctx_id_t    lnd_ctx;                /* session context */
-       gss_buffer_desc lnd_rmt_ctx;            /* remote handle of context */
-       uint32_t        lnd_seq_win;            /* sequence window */
-
-       int             lnd_rpc_err;
-       int             lnd_gss_err;
+       uint32_t        lnd_established:1;
+
+       int             lnd_secid;
+       uint32_t        lnd_uid;
+       uint32_t        lnd_lsvc;
+       char            *lnd_uuid;
+
+       gss_OID         lnd_mech;               /* mech OID */
+       gss_name_t      lnd_svc_name;           /* service name */
+       unsigned int    lnd_req_flags;          /* request flags */
+       gss_cred_id_t   lnd_cred;               /* credential */
+       gss_ctx_id_t    lnd_ctx;                /* session context */
+       gss_buffer_desc lnd_rmt_ctx;            /* remote handle of context */
+       gss_buffer_desc lnd_ctx_token;          /* context token for kernel */
+       uint32_t        lnd_seq_win;            /* sequence window */
+
+       int             lnd_rpc_err;
+       int             lnd_gss_err;
 };
 
 /*
@@ -98,20 +99,21 @@ struct lgss_init_res {
 };
 
 struct keyring_upcall_param {
-       uint32_t        kup_ver;
-       uint32_t        kup_secid;
-       uint32_t        kup_uid;
-       uint32_t        kup_fsuid;
-       uint32_t        kup_gid;
-       uint32_t        kup_fsgid;
-       uint32_t        kup_svc;
-       uint64_t        kup_nid;
-       uint64_t        kup_selfnid;
-       char            kup_tgt[64];
-       char            kup_mech[16];
-       unsigned int    kup_is_root:1,
-                       kup_is_mdt:1,
-                       kup_is_ost:1;
+       uint32_t        kup_ver;
+       uint32_t        kup_secid;
+       uint32_t        kup_uid;
+       uint32_t        kup_fsuid;
+       uint32_t        kup_gid;
+       uint32_t        kup_fsgid;
+       uint32_t        kup_svc;
+       uint64_t        kup_nid;
+       uint64_t        kup_selfnid;
+       char            kup_svc_type;
+       char            kup_tgt[64];
+       char            kup_mech[16];
+       unsigned int    kup_is_root:1,
+                       kup_is_mdt:1,
+                       kup_is_ost:1;
 };
 
 /****************************************
@@ -176,7 +178,7 @@ int do_nego_rpc(struct lgss_nego_data *lnd,
         logmsg(LL_TRACE, "do_nego_rpc: to parse reply\n");
         if (param.status) {
                logmsg(LL_ERR, "status: %ld (%s)\n",
-                      param.status, strerror((int)param.status));
+                      param.status, strerror((int)(-param.status)));
 
                 /* kernel return -ETIMEDOUT means the rpc timedout, we should
                  * notify the caller to reinitiate the gss negotiation, by
@@ -195,15 +197,21 @@ int do_nego_rpc(struct lgss_nego_data *lnd,
         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);
+       gr->gr_ctx.length = *p++;
+       gr->gr_ctx.value = malloc(gr->gr_ctx.length);
+       if (gr->gr_ctx.value == NULL)
+               return -ENOMEM;
+       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);
+       if (gr->gr_token.value == NULL) {
+               free(gr->gr_ctx.value);
+               return -ENOMEM;
+       }
+       memcpy(gr->gr_token.value, p, gr->gr_token.length);
+       p += (((gr->gr_token.length + 3) & ~3) / 4);
 
        logmsg(LL_DEBUG, "do_nego_rpc: receive handle len %zu, token len %zu, "
               "res %d\n", gr->gr_ctx.length, gr->gr_token.length, res);
@@ -321,18 +329,18 @@ static int lgssc_negotiation(struct lgss_nego_data *lnd)
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
 static int lgssc_init_nego_data(struct lgss_nego_data *lnd,
-                                struct keyring_upcall_param *kup,
-                                lgss_mech_t mech)
+                               struct keyring_upcall_param *kup,
+                               enum lgss_mech mech)
 {
         gss_buffer_desc         sname;
         OM_uint32               maj_stat, min_stat;
 
         memset(lnd, 0, sizeof(*lnd));
 
-        lnd->lnd_secid = kup->kup_secid;
-        lnd->lnd_uid = kup->kup_uid;
-        lnd->lnd_lsvc = kup->kup_svc;
-        lnd->lnd_uuid = kup->kup_tgt;
+       lnd->lnd_secid = kup->kup_secid;
+       lnd->lnd_uid = kup->kup_uid;
+       lnd->lnd_lsvc = kup->kup_svc | mech << LUSTRE_GSS_MECH_SHIFT;
+       lnd->lnd_uuid = kup->kup_tgt;
 
         lnd->lnd_established = 0;
         lnd->lnd_svc_name = GSS_C_NO_NAME;
@@ -474,21 +482,14 @@ out:
         return rc;
 }
 
-/*
- * note we inherited assumed authority from parent process
- */
-static int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
-                              struct keyring_upcall_param *kup)
+static int lgssc_kr_negotiate_krb(key_serial_t keyid, struct lgss_cred *cred,
+                                 struct keyring_upcall_param *kup)
 {
-        struct lgss_nego_data   lnd;
-        gss_buffer_desc         token = GSS_C_EMPTY_BUFFER;
-        OM_uint32               min_stat;
-        int                     rc = -1;
+       struct lgss_nego_data lnd;
+       OM_uint32 min_stat;
+       int rc = -1;
 
-       logmsg(LL_TRACE, "child start on behalf of key %08x: "
-              "cred %p, uid %u, svc %u, nid %"PRIx64", uids: %u:%u/%u:%u\n",
-              keyid, cred, cred->lc_uid, cred->lc_tgt_svc, cred->lc_tgt_nid,
-              kup->kup_uid, kup->kup_gid, kup->kup_fsuid, kup->kup_fsgid);
+       memset(&lnd, 0, sizeof(lnd));
 
         if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
                 logmsg(LL_ERR, "key %08x: failed to construct service "
@@ -517,29 +518,53 @@ static int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
                 goto out;
         }
 
-        rc = serialize_context_for_kernel(lnd.lnd_ctx, &token, lnd.lnd_mech);
-        if (rc) {
-                logmsg(LL_ERR, "key %08x: failed to export context\n", keyid);
-                error_kernel_key(keyid, rc, lnd.lnd_gss_err);
-                goto out;
-        }
+       rc = serialize_context_for_kernel(lnd.lnd_ctx, &lnd.lnd_ctx_token,
+                                         lnd.lnd_mech);
+       if (rc) {
+               logmsg(LL_ERR, "key %08x: failed to export context\n", keyid);
+               error_kernel_key(keyid, rc, lnd.lnd_gss_err);
+               goto out;
+       }
 
-        rc = update_kernel_key(keyid,  &lnd, &token);
-        if (rc)
-                goto out;
+       rc = update_kernel_key(keyid,  &lnd, &lnd.lnd_ctx_token);
+       if (rc)
+               goto out;
 
-        rc = 0;
-        logmsg(LL_INFO, "key %08x for user %u is updated OK!\n",
-               keyid, kup->kup_uid);
+       rc = 0;
+       logmsg(LL_INFO, "key %08x for user %u is updated OK!\n",
+              keyid, kup->kup_uid);
 out:
-        if (token.length != 0)
-                gss_release_buffer(&min_stat, &token);
+       if (lnd.lnd_ctx_token.length != 0)
+               gss_release_buffer(&min_stat, &lnd.lnd_ctx_token);
 
-        lgssc_fini_nego_data(&lnd);
+       lgssc_fini_nego_data(&lnd);
 
 out_cred:
-        lgss_release_cred(cred);
-        return rc;
+       lgss_release_cred(cred);
+       return rc;
+}
+
+/*
+ * note we inherited assumed authority from parent process
+ */
+static int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
+                             struct keyring_upcall_param *kup)
+{
+       int rc;
+
+       logmsg(LL_TRACE, "child start on behalf of key %08x: "
+              "cred %p, uid %u, svc %u, nid %"PRIx64", uids: %u:%u/%u:%u\n",
+              keyid, cred, cred->lc_uid, cred->lc_tgt_svc, cred->lc_tgt_nid,
+              kup->kup_uid, kup->kup_gid, kup->kup_fsuid, kup->kup_fsgid);
+
+       switch (cred->lc_mech->lmt_mech_n) {
+       case LGSS_MECH_KRB5:
+       default:
+               rc = lgssc_kr_negotiate_krb(keyid, cred, kup);
+               break;
+       }
+
+       return rc;
 }
 
 /*
@@ -549,15 +574,16 @@ out_cred:
  *  [2]: uid            (uint)
  *  [3]: gid            (uint)
  *  [4]: flags          (string) FMT: r-root; m-mdt; o-ost
- *  [5]: lustre_svc     (uint)
- *  [6]: target_nid     (uint64)
- *  [7]: target_uuid    (string)
- *  [8]: self_nid        (uint64)
+ *  [5]: svc type       (char)
+ *  [6]: lustre_svc     (int)
+ *  [7]: target_nid     (uint64)
+ *  [8]: target_uuid    (string)
+ *  [9]: self_nid        (uint64)
  */
 static int parse_callout_info(const char *coinfo,
                               struct keyring_upcall_param *uparam)
 {
-       const int       nargs = 9;
+       const int       nargs = 10;
        char            buf[1024];
        char           *string = buf;
        int             length, i;
@@ -584,9 +610,9 @@ static int parse_callout_info(const char *coinfo,
         }
         data[i] = string;
 
-       logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%s,%s,%s,%s\n",
-              data[0], data[1], data[2], data[3], data[4], data[5],
-              data[6], data[7], data[8]);
+       logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%c,%s,%s,%s,%s\n",
+              data[0], data[1], data[2], data[3], data[4], data[5][0],
+              data[6], data[7], data[8], data[9]);
 
        uparam->kup_secid = strtol(data[0], NULL, 0);
        strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
@@ -598,19 +624,20 @@ static int parse_callout_info(const char *coinfo,
                uparam->kup_is_mdt = 1;
        if (strchr(data[4], 'o'))
                uparam->kup_is_ost = 1;
-       uparam->kup_svc = strtol(data[5], NULL, 0);
-       uparam->kup_nid = strtoll(data[6], NULL, 0);
-       strlcpy(uparam->kup_tgt, data[7], sizeof(uparam->kup_tgt));
-       uparam->kup_selfnid = strtoll(data[8], NULL, 0);
+       uparam->kup_svc_type = data[5][0];
+       uparam->kup_svc = strtol(data[6], NULL, 0);
+       uparam->kup_nid = strtoll(data[7], NULL, 0);
+       strlcpy(uparam->kup_tgt, data[8], sizeof(uparam->kup_tgt));
+       uparam->kup_selfnid = strtoll(data[9], NULL, 0);
 
        logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u, "
-              "is_root %d, is_mdt %d, is_ost %d, svc %d, nid 0x%"PRIx64", "
-              "tgt %s, self nid 0x%"PRIx64"\n",
+              "is_root %d, is_mdt %d, is_ost %d, svc type %c, svc %d, "
+              "nid 0x%"PRIx64", tgt %s, self nid 0x%"PRIx64"\n",
               uparam->kup_secid, uparam->kup_mech,
               uparam->kup_uid, uparam->kup_gid,
               uparam->kup_is_root, uparam->kup_is_mdt, uparam->kup_is_ost,
-              uparam->kup_svc, uparam->kup_nid, uparam->kup_tgt,
-              uparam->kup_selfnid);
+              uparam->kup_svc_type, uparam->kup_svc, uparam->kup_nid,
+              uparam->kup_tgt, uparam->kup_selfnid);
        return 0;
 }
 
@@ -743,6 +770,8 @@ int main(int argc, char *argv[])
        cred->lc_root_flags |= uparam.kup_is_ost ? LGSS_ROOT_CRED_OST : 0;
        cred->lc_tgt_nid = uparam.kup_nid;
        cred->lc_tgt_svc = uparam.kup_svc;
+       cred->lc_tgt_uuid = uparam.kup_tgt;
+       cred->lc_svc_type = uparam.kup_svc_type;
        cred->lc_self_nid = uparam.kup_selfnid;
 
         if (lgss_prepare_cred(cred)) {
index 6f13f8f..14f0f72 100644 (file)
@@ -224,11 +224,23 @@ int lgss_mutex_unlock(lgss_mutex_id_t mid)
  ****************************************/
 
 /* from kerberos source, gssapi_krb5.c */
-gss_OID_desc krb5oid =
-        {9, "\052\206\110\206\367\022\001\002\002"};
-
-gss_OID_desc spkm3oid =
-        {7, "\053\006\001\005\005\001\003"};
+gss_OID_desc krb5oid = {
+       .length = 9,
+       .elements = "\052\206\110\206\367\022\001\002\002"
+};
+gss_OID_desc spkm3oid = {
+       .length = 7,
+       .elements = "\053\006\001\005\005\001\003"
+};
+/* null and sk come from IU's oid space */
+gss_OID_desc nulloid = {
+       .length = 12,
+       .elements = "\053\006\001\004\001\311\146\215\126\001\000\000"
+};
+gss_OID_desc skoid = {
+       .length = 12,
+       .elements = "\053\006\001\004\001\311\146\215\126\001\000\001"
+};
 
 /****************************************
  * log facilities                       *
@@ -362,7 +374,7 @@ struct lgss_cred * lgss_create_cred(struct lgss_mech_type *mech)
 
 void lgss_destroy_cred(struct lgss_cred *cred)
 {
-        lassert(cred->lc_mech);
+       lassert(cred->lc_mech != NULL);
         lassert(cred->lc_mech_cred == NULL);
 
         logmsg(LL_TRACE, "destroying a %s cred at %p\n",
@@ -374,7 +386,7 @@ int lgss_prepare_cred(struct lgss_cred *cred)
 {
         struct lgss_mech_type   *mech = cred->lc_mech;
 
-        lassert(mech);
+       lassert(mech != NULL);
 
         logmsg(LL_TRACE, "preparing %s cred %p\n", mech->lmt_name, cred);
 
@@ -387,13 +399,13 @@ void lgss_release_cred(struct lgss_cred *cred)
 {
         struct lgss_mech_type   *mech = cred->lc_mech;
 
-        lassert(mech);
+       lassert(mech != NULL);
 
         logmsg(LL_TRACE, "releasing %s cred %p\n", mech->lmt_name, cred);
 
         if (cred->lc_mech_cred) {
                 lassert(cred->lc_mech != NULL);
-                lassert(cred->lc_mech->lmt_release_cred);
+               lassert(cred->lc_mech->lmt_release_cred != NULL);
 
                 cred->lc_mech->lmt_release_cred(cred);
         }
@@ -403,7 +415,7 @@ int lgss_using_cred(struct lgss_cred *cred)
 {
         struct lgss_mech_type   *mech = cred->lc_mech;
 
-        lassert(mech);
+       lassert(mech != NULL);
 
         logmsg(LL_TRACE, "using %s cred %p\n", mech->lmt_name, cred);
 
@@ -412,6 +424,22 @@ int lgss_using_cred(struct lgss_cred *cred)
         return 0;
 }
 
+int lgss_validate_cred(struct lgss_cred *cred, gss_buffer_desc *token,
+                      gss_buffer_desc *ctx_token)
+{
+       struct lgss_mech_type *mech = cred->lc_mech;
+
+       lassert(mech != NULL);
+
+       logmsg(LL_TRACE, "validate %s cred %p with token %p\n", mech->lmt_name,
+              cred, token);
+
+       if (mech->lmt_validate_cred)
+               return mech->lmt_validate_cred(cred, token, ctx_token);
+
+       return 0;
+}
+
 /****************************************
  * helper functions                     *
  ****************************************/
index 1c0e377..3417aa6 100644 (file)
@@ -44,6 +44,8 @@
 #include <stdint.h>
 #include <gssapi/gssapi.h>
 
+#include "lsupport.h"
+
 #define LGSS_SVC_MGS_STR        "lustre_mgs"
 #define LGSS_SVC_MDS_STR        "lustre_mds"
 #define LGSS_SVC_OSS_STR        "lustre_oss"
@@ -63,8 +65,8 @@ extern const char *lgss_svc_str[LGSS_SVC_MAX];
  ****************************************/
 
 typedef enum {
-        LGSS_MUTEX_KRB5         = 0,
-        LGSS_MUTEX_MAX
+       LGSS_MUTEX_KRB5 = 0,
+       LGSS_MUTEX_MAX
 } lgss_mutex_id_t;
 
 int lgss_mutex_lock(lgss_mutex_id_t mid);
@@ -138,10 +140,8 @@ do {                                                                    \
 
 extern gss_OID_desc krb5oid;
 extern gss_OID_desc spkm3oid;
-
-typedef enum {
-        LGSS_MECH_KRB5  = 0,
-} lgss_mech_t;
+extern gss_OID_desc nulloid;
+extern gss_OID_desc skoid;
 
 /****************************************
  * client credentials                   *
@@ -150,14 +150,17 @@ typedef enum {
 struct lgss_cred;
 
 struct lgss_mech_type {
-        char               *lmt_name;
-        lgss_mech_t         lmt_mech_n;
-
-        int                (*lmt_init)(void);
-        void               (*lmt_fini)(void);
-        int                (*lmt_prepare_cred)(struct lgss_cred *cred);
-        void               (*lmt_release_cred)(struct lgss_cred *cred);
-        int                (*lmt_using_cred)(struct lgss_cred *cred);
+       char            *lmt_name;
+       enum lgss_mech   lmt_mech_n;
+
+       int              (*lmt_init)(void);
+       void             (*lmt_fini)(void);
+       int              (*lmt_prepare_cred)(struct lgss_cred *cred);
+       void             (*lmt_release_cred)(struct lgss_cred *cred);
+       int              (*lmt_using_cred)(struct lgss_cred *cred);
+       int              (*lmt_validate_cred)(struct lgss_cred *cred,
+                                             gss_buffer_desc *token,
+                                             gss_buffer_desc *ctx_token);
 };
 
 enum {
@@ -169,14 +172,17 @@ enum {
 };
 
 struct lgss_cred {
-       int                     lc_uid;
-       unsigned int            lc_root_flags;
-       uint64_t                lc_self_nid;
-       uint64_t                lc_tgt_nid;
-       uint32_t                lc_tgt_svc;
-
-       struct lgss_mech_type  *lc_mech;
-       void                   *lc_mech_cred;
+       int                     lc_uid;
+       unsigned int            lc_root_flags;
+       uint64_t                lc_self_nid;
+       uint64_t                lc_tgt_nid;
+       uint32_t                lc_tgt_svc;
+       char                    lc_svc_type;
+       char                    *lc_tgt_uuid;
+
+       struct lgss_mech_type   *lc_mech;
+       void                    *lc_mech_cred;
+       gss_buffer_desc         lc_mech_token;
 };
 
 struct lgss_mech_type *lgss_name2mech(const char *mech_name);
@@ -188,13 +194,11 @@ void lgss_destroy_cred(struct lgss_cred *cred);
 int lgss_prepare_cred(struct lgss_cred *cred);
 void lgss_release_cred(struct lgss_cred *cred);
 int lgss_using_cred(struct lgss_cred *cred);
+int lgss_validate_cred(struct lgss_cred *cred, gss_buffer_desc *token,
+                      gss_buffer_desc *ctx_token);
 
 int lgss_get_service_str(char **string, uint32_t lsvc, uint64_t tgt_nid);
 
-
-extern gss_OID_desc krb5oid;
-extern gss_OID_desc spkm3oid;
-
 static inline
 int gss_OID_equal(gss_OID_desc *oid1, gss_OID_desc *oid2)
 {
index 0745ad1..f01b3cf 100644 (file)
@@ -56,8 +56,18 @@ void gssd_exit_unique(int type);
 #define LUSTRE_GSS_SVC_MDS      1
 #define LUSTRE_GSS_SVC_OSS      2
 
+#define LUSTRE_GSS_SVC_MASK    0x0000FFFF
+#define LUSTRE_GSS_MECH_MASK   0xFFFF0000
+#define LUSTRE_GSS_MECH_SHIFT  16
+
 extern const char * lustre_svc_name[];
 
+enum lgss_mech {
+       LGSS_MECH_KRB5  = 0,
+       LGSS_MECH_NULL  = 1,
+       LGSS_MECH_SK    = 2,
+};
+
 struct lgssd_upcall_data {
         uint32_t        seq;
         uint32_t        uid;
index 457d991..4ae3a17 100644 (file)
@@ -176,10 +176,18 @@ sig_hup(int signal)
 }
 
 static void
-usage(char *progname)
+usage(FILE *fp, char *progname)
 {
-       fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o] [-g]\n",
+       fprintf(fp, "usage: %s [ -fnvmogk ]\n",
                progname);
+       fprintf(stderr, "-f      - Run in foreground\n");
+       fprintf(stderr, "-n      - Don't establish kerberos credentials\n");
+       fprintf(stderr, "-v      - Verbosity\n");
+       fprintf(stderr, "-m      - Service MDS\n");
+       fprintf(stderr, "-o      - Service OSS\n");
+       fprintf(stderr, "-g      - Service MGS\n");
+       fprintf(stderr, "-k      - Enable kerberos support\n");
+
        exit(1);
 }
 
@@ -191,35 +199,40 @@ main(int argc, char *argv[])
        int verbosity = 0;
        int opt;
        int must_srv_mds = 0, must_srv_oss = 0, must_srv_mgs = 0;
-       extern char *optarg;
        char *progname;
 
-       while ((opt = getopt(argc, argv, "fvrnmog:")) != -1) {
+       while ((opt = getopt(argc, argv, "fnvmogk")) != -1) {
                switch (opt) {
-                       case 'f':
-                               fg = 1;
-                               break;
-                       case 'n':
-                               get_creds = 0;
-                               break;
-                       case 'v':
-                               verbosity++;
-                               break;
-                       case 'm':
-                               get_creds = 1;
-                               must_srv_mds = 1;
-                               break;
-                       case 'o':
-                               get_creds = 1;
-                               must_srv_oss = 1;
-                               break;
-                       case 'g':
-                               get_creds = 1;
-                               must_srv_mgs = 1;
-                               break;
-                       default:
-                               usage(argv[0]);
-                               break;
+               case 'f':
+                       fg = 1;
+                       break;
+               case 'n':
+                       get_creds = 0;
+                       break;
+               case 'v':
+                       verbosity++;
+                       break;
+               case 'm':
+                       get_creds = 1;
+                       must_srv_mds = 1;
+                       break;
+               case 'o':
+                       get_creds = 1;
+                       must_srv_oss = 1;
+                       break;
+               case 'g':
+                       get_creds = 1;
+                       must_srv_mgs = 1;
+                       break;
+               case 'k':
+                       krb_enabled = 1;
+                       break;
+               case 'h':
+                       usage(stdout, argv[0]);
+                       break;
+               default:
+                       usage(stderr, argv[0]);
+                       break;
                }
        }
 
@@ -230,23 +243,23 @@ main(int argc, char *argv[])
 
        initerr(progname, verbosity, fg);
 
-       if (gssd_check_mechs() != 0) {
-               printerr(0, "ERROR: Problem with gssapi library\n");
-               exit(1);
-       }
+       /* For kerberos use gss mechanisms but ignore for sk and null */
+       if (krb_enabled && gssd_check_mechs() == 0) {
+               if (gssd_get_local_realm()) {
+                       printerr(0, "ERROR: Can't get Local Kerberos realm\n");
+                       exit(1);
+               }
 
-       if (gssd_get_local_realm()) {
-               printerr(0, "ERROR: Can't get Local Kerberos realm\n");
-               exit(1);
-       }
-  
-       if (get_creds &&
-           gssd_prepare_creds(must_srv_mgs, must_srv_mds, must_srv_oss)) {
-                printerr(0, "unable to obtain root (machine) credentials\n");
-                printerr(0, "do you have a keytab entry for "
-                           "<lustre_xxs>/<your.host>@<YOUR.REALM> in "
-                           "/etc/krb5.keytab?\n");
-               exit(1);
+               if (get_creds &&
+                   gssd_prepare_creds(must_srv_mgs, must_srv_mds,
+                                      must_srv_oss)) {
+                       printerr(0, "unable to obtain root (machine) "
+                                "credentials\n");
+                       printerr(0, "do you have a keytab entry for "
+                                "<lustre_xxs>/<your.host>@<YOUR.REALM> in "
+                                "/etc/krb5.keytab?\n");
+                       exit(1);
+               }
        }
 
        if (!fg)
index a2eece6..94b95a3 100644 (file)
@@ -35,7 +35,9 @@
 #include <sys/queue.h>
 #include <gssapi/gssapi.h>
 
-int handle_nullreq(FILE *f);
+int krb_enabled;
+
+int handle_channel_request(FILE *f);
 void svcgssd_run(void);
 int gssd_prepare_creds(int must_srv_mgs, int must_srv_mds, int must_srv_oss);
 gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
index bd5fea7..c8cfb41 100644 (file)
 void
 svcgssd_run()
 {
+       static const char gss_rpc_channel_path[] =
+               "/proc/net/rpc/auth.sptlrpc.init/channel";
        int                     ret;
        FILE                    *f = NULL;
        struct pollfd           pollfd;
        struct timespec         halfsec = { .tv_sec = 0, .tv_nsec = 500000000 };
 
-#define NULLRPC_FILE "/proc/net/rpc/auth.sptlrpc.init/channel"
-
        while (1) {
                int save_err;
 
                while (f == NULL) {
-                       f = fopen(NULLRPC_FILE, "rw");
+                       f = fopen(gss_rpc_channel_path, "rw");
                        if (f == NULL) {
                                printerr(4, "failed to open %s: %s\n",
-                                        NULLRPC_FILE, strerror(errno));
+                                        gss_rpc_channel_path, strerror(errno));
                                nanosleep(&halfsec, NULL);
                        } else {
                                printerr(1, "successfully open %s\n",
-                                        NULLRPC_FILE);
+                                        gss_rpc_channel_path);
                                break;
                        }
                }
@@ -95,7 +95,7 @@ svcgssd_run()
                        fclose(f);
                        f = NULL;
                } else if (ret == 0) {
-                       printerr(3, "poll timeout\n");
+                       printerr(4, "poll timeout\n");
                } else {
                        if (ret != 1) {
                                printerr(0, "bug: unexpected poll return %d\n",
@@ -103,7 +103,7 @@ svcgssd_run()
                                exit(1);
                        }
                        if (pollfd.revents & POLLIN) {
-                               if (handle_nullreq(f) < 0) {
+                               if (handle_channel_request(f) < 0) {
                                        fclose(f);
                                        f = NULL;
                                }
index 22c3ed8..ca98f42 100644 (file)
    (((o1)->length == (o2)->length) && \
     (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
 
-struct mech2file {
+struct oid2mech {
        gss_OID_desc mech;
-       char         filename[8];
+       char         mechname[8];
 };
 
-struct mech2file m2f[] = {
+static const struct oid2mech o2m[] = {
        {{9, "\052\206\110\206\367\022\001\002\002"}, "krb5"},
        {{7, "\053\006\001\005\005\001\003"}, "spkm3"},
        {{7, "\053\006\001\005\005\001\009"}, "lipkey"},
+       {{12, "\053\006\001\004\001\311\146\215\126\001\000\000"}, "gssnull"},
+       {{12, "\053\006\001\004\001\311\146\215\126\001\000\001"}, "sk"},
        {{0,0},""},
 };
 
 /*
  * Find the Linux svcgssd downcall file name given the mechanism
  */
-char *
-mech2file(gss_OID mech)
+const char *gss_OID_mech_name(gss_OID mech)
 {
-       struct mech2file *m2fp = m2f;
+       const struct oid2mech *o2mp = o2m;
 
-       while(m2fp->mech.length != 0) {
-               if (g_OID_equal(mech,&m2fp->mech))
-                       return(m2fp->filename);
-               m2fp++;
+       while (o2mp->mech.length != 0) {
+               if (g_OID_equal(mech, &o2mp->mech))
+                       return o2mp->mechname;
+               o2mp++;
        }
        return NULL;
 }
index 588b524..508a3ad 100644 (file)
 # include <netdb.h>
 #endif
 
+#include <stdbool.h>
+#include <lnet/nidstr.h>
+
 #include "svcgssd.h"
 #include "gss_util.h"
 #include "err_util.h"
 #include "context.h"
 #include "cacheio.h"
 #include "lsupport.h"
+#include "gss_oids.h"
+#include <lustre/lustre_idl.h>
+
+extern const char *gss_OID_mech_name(gss_OID mech);
 
-extern char * mech2file(gss_OID mech);
 #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.sptlrpc.context/channel"
 #define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.sptlrpc.init/channel"
 
@@ -73,16 +79,36 @@ struct svc_cred {
        uid_t    cr_gid;
 };
 
+struct svc_nego_data {
+       /* kernel data*/
+       uint32_t        lustre_svc;
+       lnet_nid_t      nid;
+       uint64_t        handle_seq;
+       char            nm_name[LUSTRE_NODEMAP_NAME_LENGTH + 1];
+       gss_buffer_desc in_tok;
+       gss_buffer_desc out_tok;
+       gss_buffer_desc in_handle;
+       gss_buffer_desc out_handle;
+       uint32_t        maj_stat;
+       uint32_t        min_stat;
+
+       /* userspace data */
+       gss_OID                 mech;
+       gss_ctx_id_t            ctx;
+       gss_buffer_desc         ctx_token;
+};
+
 static int
 do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
-               gss_OID mech, gss_buffer_desc *context_token)
+               gss_OID mechoid, gss_buffer_desc *context_token)
 {
        FILE *f;
-       char *fname = NULL;
+       const char *mechname;
        int err;
 
        printerr(2, "doing downcall\n");
-       if ((fname = mech2file(mech)) == NULL)
+       mechname = gss_OID_mech_name(mechoid);
+       if (mechname == NULL)
                goto out_err;
        f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
        if (f == NULL) {
@@ -93,7 +119,7 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
        }
        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, 3600); /* an hour should be sufficient */
        qword_printint(f, cred->cr_remote);
        qword_printint(f, cred->cr_usr_root);
        qword_printint(f, cred->cr_usr_mds);
@@ -101,7 +127,7 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
        qword_printint(f, cred->cr_mapped_uid);
        qword_printint(f, cred->cr_uid);
        qword_printint(f, cred->cr_gid);
-       qword_print(f, fname);
+       qword_print(f, mechname);
        qword_printhex(f, context_token->value, context_token->length);
        err = qword_eol(f);
        fclose(f);
@@ -133,7 +159,7 @@ send_response(FILE *f, gss_buffer_desc *in_handle, gss_buffer_desc *in_token,
 
        qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
        qword_addhex(&bp, &blen, in_token->value, in_token->length);
-       qword_addint(&bp, &blen, 0x7fffffff); /*XXX need a better timeout */
+       qword_addint(&bp, &blen, 3600); /* an hour should be sufficient */
        qword_adduint(&bp, &blen, maj_stat);
        qword_adduint(&bp, &blen, min_stat);
        qword_addhex(&bp, &blen, out_handle->value, out_handle->length);
@@ -466,153 +492,198 @@ typedef struct gss_union_ctx_id_t {
        gss_ctx_id_t    internal_ctx_id;
 } gss_union_ctx_id_desc, *gss_union_ctx_id_t;
 
+static int handle_krb(struct svc_nego_data *snd)
+{
+       u_int32_t               ret_flags;
+       gss_name_t              client_name;
+       gss_buffer_desc         ignore_out_tok = {.value = NULL};
+       gss_OID                 mech = GSS_C_NO_OID;
+       gss_cred_id_t           svc_cred;
+       u_int32_t               ignore_min_stat;
+       struct svc_cred         cred;
+
+       svc_cred = gssd_select_svc_cred(snd->lustre_svc);
+       if (!svc_cred) {
+               printerr(0, "no service credential for svc %u\n",
+                        snd->lustre_svc);
+               goto out_err;
+       }
+
+       snd->maj_stat = gss_accept_sec_context(&snd->min_stat, &snd->ctx,
+                                              svc_cred, &snd->in_tok,
+                                              GSS_C_NO_CHANNEL_BINDINGS,
+                                              &client_name, &mech,
+                                              &snd->out_tok, &ret_flags, NULL,
+                                              NULL);
+
+       if (snd->maj_stat == GSS_S_CONTINUE_NEEDED) {
+               printerr(1, "gss_accept_sec_context GSS_S_CONTINUE_NEEDED\n");
+
+               /* Save the context handle for future calls */
+               snd->out_handle.length = sizeof(snd->ctx);
+               memcpy(snd->out_handle.value, &snd->ctx, sizeof(snd->ctx));
+               return 0;
+       } else if (snd->maj_stat != GSS_S_COMPLETE) {
+               printerr(0, "WARNING: gss_accept_sec_context failed\n");
+               pgsserr("handle_krb: gss_accept_sec_context",
+                       snd->maj_stat, snd->min_stat, mech);
+               goto out_err;
+       }
+
+       if (get_ids(client_name, mech, &cred, snd->nid, snd->lustre_svc)) {
+               /* get_ids() prints error msg */
+               snd->maj_stat = GSS_S_BAD_NAME; /* XXX ? */
+               gss_release_name(&ignore_min_stat, &client_name);
+               goto out_err;
+       }
+       gss_release_name(&ignore_min_stat, &client_name);
+
+       /* Context complete. Pass handle_seq in out_handle to use
+        * for context lookup in the kernel. */
+       snd->out_handle.length = sizeof(snd->handle_seq);
+       memcpy(snd->out_handle.value, &snd->handle_seq,
+              sizeof(snd->handle_seq));
+
+       /* kernel needs ctx to calculate verifier on null response, so
+        * must give it context before doing null call: */
+       if (serialize_context_for_kernel(snd->ctx, &snd->ctx_token, mech)) {
+               printerr(0, "WARNING: handle_krb: "
+                        "serialize_context_for_kernel failed\n");
+               snd->maj_stat = GSS_S_FAILURE;
+               goto out_err;
+       }
+       /* We no longer need the gss context */
+       gss_delete_sec_context(&ignore_min_stat, &snd->ctx, &ignore_out_tok);
+       do_svc_downcall(&snd->out_handle, &cred, mech, &snd->ctx_token);
+
+       return 0;
+
+out_err:
+       if (snd->ctx != GSS_C_NO_CONTEXT)
+               gss_delete_sec_context(&ignore_min_stat, &snd->ctx,
+                                      &ignore_out_tok);
+
+       return 1;
+}
+
 /*
  * return -1 only if we detect error during reading from upcall channel,
  * all other cases return 0.
  */
-int
-handle_nullreq(FILE *f) {
-       uint64_t                handle_seq;
+int handle_channel_request(FILE *f)
+{
        char                    in_tok_buf[TOKEN_BUF_SIZE];
        char                    in_handle_buf[15];
        char                    out_handle_buf[15];
-       gss_buffer_desc         in_tok = {.value = in_tok_buf},
-                               out_tok = {.value = NULL},
-                               in_handle = {.value = in_handle_buf},
-                               out_handle = {.value = out_handle_buf},
-                               ctx_token = {.value = NULL},
-                               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;
-       int                     get_len;
-       struct svc_cred         cred;
-       static char             *lbuf = NULL;
-       static int              lbuflen = 0;
+       gss_buffer_desc         ctx_token      = {.value = NULL},
+                               null_token     = {.value = NULL};
+       uint32_t                lustre_mech;
+       static char             *lbuf;
+       static int              lbuflen;
        static char             *cp;
-
-       printerr(2, "handling null request\n");
-
+       int                     get_len;
+       int                     rc = 1;
+       u_int32_t               ignore_min_stat;
+       struct svc_nego_data    snd = {
+               .in_tok.value           = in_tok_buf,
+               .in_handle.value        = in_handle_buf,
+               .out_handle.value       = out_handle_buf,
+               .maj_stat               = GSS_S_FAILURE,
+               .ctx                    = GSS_C_NO_CONTEXT,
+       };
+
+       printerr(2, "handling request\n");
        if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
-               printerr(0, "WARNING: handle_nullreq: "
-                           "failed reading request\n");
+               printerr(0, "WARNING: handle_req: failed reading request\n");
                return -1;
        }
 
        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(2, "handling req: svc %u, nid %016llx, idx %"PRIx64"\n",
-                lustre_svc, nid, handle_seq);
+       /* see rsi_request() for the format of data being input here */
+       qword_get(&cp, (char *)&snd.lustre_svc, sizeof(snd.lustre_svc));
+
+       /* lustre_svc is the svc and gss subflavor */
+       lustre_mech = (snd.lustre_svc & LUSTRE_GSS_MECH_MASK) >>
+                     LUSTRE_GSS_MECH_SHIFT;
+       snd.lustre_svc = snd.lustre_svc & LUSTRE_GSS_SVC_MASK;
+       switch (lustre_mech) {
+       case LGSS_MECH_KRB5:
+               if (!krb_enabled) {
+                       printerr(1, "WARNING: Request for kerberos but service "
+                                "support not enabled\n");
+                       goto ignore;
+               }
+               snd.mech = &krb5oid;
+               break;
+       default:
+               printerr(0, "WARNING: invalid mechanism recevied: %d\n",
+                        lustre_mech);
+               goto out_err;
+               break;
+       }
+
+       qword_get(&cp, (char *)&snd.nid, sizeof(snd.nid));
+       qword_get(&cp, (char *)&snd.handle_seq, sizeof(snd.handle_seq));
+       qword_get(&cp, snd.nm_name, sizeof(snd.nm_name));
+       printerr(2, "handling req: svc %u, nid %016llx, idx %"PRIx64" nodemap "
+                "%s\n", snd.lustre_svc, snd.nid, snd.handle_seq, snd.nm_name);
 
-       get_len = qword_get(&cp, in_handle.value, sizeof(in_handle_buf));
+       get_len = qword_get(&cp, snd.in_handle.value, sizeof(in_handle_buf));
        if (get_len < 0) {
-               printerr(0, "WARNING: handle_nullreq: "
-                           "failed parsing request\n");
+               printerr(0, "WARNING: handle_req: failed parsing request\n");
                goto out_err;
        }
-       in_handle.length = (size_t)get_len;
+       snd.in_handle.length = (size_t)get_len;
 
        printerr(3, "in_handle:\n");
-       print_hexl(3, in_handle.value, in_handle.length);
+       print_hexl(3, snd.in_handle.value, snd.in_handle.length);
 
-       get_len = qword_get(&cp, in_tok.value, sizeof(in_tok_buf));
+       get_len = qword_get(&cp, snd.in_tok.value, sizeof(in_tok_buf));
        if (get_len < 0) {
-               printerr(0, "WARNING: handle_nullreq: "
-                           "failed parsing request\n");
+               printerr(0, "WARNING: handle_req: failed parsing request\n");
                goto out_err;
        }
-       in_tok.length = (size_t)get_len;
+       snd.in_tok.length = (size_t)get_len;
 
        printerr(3, "in_tok:\n");
-       print_hexl(3, in_tok.value, in_tok.length);
+       print_hexl(3, snd.in_tok.value, snd.in_tok.length);
 
-       if (in_handle.length != 0) { /* CONTINUE_INIT case */
-               if (in_handle.length != sizeof(ctx)) {
-                       printerr(0, "WARNING: handle_nullreq: "
+       if (snd.in_handle.length != 0) { /* CONTINUE_INIT case */
+               if (snd.in_handle.length != sizeof(snd.ctx)) {
+                       printerr(0, "WARNING: handle_req: "
                                    "input handle has unexpected length %zu\n",
-                                   in_handle.length);
+                                   snd.in_handle.length);
                        goto out_err;
                }
                /* in_handle is the context id stored in the out_handle
                 * for the GSS_S_CONTINUE_NEEDED case below.  */
-               memcpy(&ctx, in_handle.value, in_handle.length);
-       }
-
-       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;
-       }
-
-       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 (maj_stat == GSS_S_CONTINUE_NEEDED) {
-               printerr(1, "gss_accept_sec_context GSS_S_CONTINUE_NEEDED\n");
-
-               /* Save the context handle for future calls */
-               out_handle.length = sizeof(ctx);
-               memcpy(out_handle.value, &ctx, sizeof(ctx));
-               goto continue_needed;
-       }
-       else if (maj_stat != GSS_S_COMPLETE) {
-               printerr(0, "WARNING: gss_accept_sec_context failed\n");
-               pgsserr("handle_nullreq: gss_accept_sec_context",
-                       maj_stat, min_stat, mech);
-               goto out_err;
+               memcpy(&snd.ctx, snd.in_handle.value, snd.in_handle.length);
        }
 
-       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);
-               goto out_err;
-       }
-       gss_release_name(&ignore_min_stat, &client_name);
-
-       /* Context complete. Pass handle_seq in out_handle to use
-        * for context lookup in the kernel. */
-       out_handle.length = sizeof(handle_seq);
-       memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
+       if (lustre_mech == LGSS_MECH_KRB5)
+               rc = handle_krb(&snd);
+       else
+               printerr(0, "WARNING: Received or request for"
+                        "subflavor that is not enabled: %d\n", lustre_mech);
 
-       /* kernel needs ctx to calculate verifier on null response, so
-        * must give it context before doing null call: */
-       if (serialize_context_for_kernel(ctx, &ctx_token, mech)) {
-               printerr(0, "WARNING: handle_nullreq: "
-                           "serialize_context_for_kernel failed\n");
-               maj_stat = GSS_S_FAILURE;
-               goto out_err;
-       }
-       /* We no longer need the gss context */
-       gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
+out_err:
+       /* Failures send a null token */
+       if (rc == 0)
+               send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
+                             snd.min_stat, &snd.out_handle, &snd.out_tok);
+       else
+               send_response(f, &snd.in_handle, &snd.in_tok, snd.maj_stat,
+                             snd.min_stat, &null_token, &null_token);
 
-       do_svc_downcall(&out_handle, &cred, mech, &ctx_token);
-continue_needed:
-       send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
-                       &out_handle, &out_tok);
-out:
-       if (ctx_token.value != NULL)
+       /* cleanup buffers */
+       if (snd.ctx_token.value != NULL)
                free(ctx_token.value);
-       if (out_tok.value != NULL)
-               gss_release_buffer(&ignore_min_stat, &out_tok);
-       return 0;
+       if (snd.out_tok.value != NULL)
+               gss_release_buffer(&ignore_min_stat, &snd.out_tok);
 
-out_err:
-       if (ctx != GSS_C_NO_CONTEXT)
-               gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
-       send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
-                       &null_token, &null_token);
-       goto out;
+       /* For junk wire data just ignore */
+ignore:
+       return 0;
 }
+