Whamcloud - gitweb
LU-4307 kerberos: compile errors with gss/kerberos support
[fs/lustre-release.git] / lustre / utils / gss / lgss_keyring.c
index cf267ad..7e28ce2 100644 (file)
@@ -1,29 +1,43 @@
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *  lucall_keyring.c
- *  user-space upcall to create GSS context, using keyring interface to kernel
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
  *
- *  Copyright (c) 2007 Cluster File Systems, Inc.
- *   Author: Eric Mei <ericm@clusterfs.com>
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
  *
- *   This file is part of the Lustre file system, http://www.lustre.org
- *   Lustre is a trademark of Cluster File Systems, Inc.
+ * Copyright (c) 2011, Intel Corporation.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
  *
- *   You may have signed or agreed to another license before downloading
- *   this software.  If so, you are bound by the terms and conditions
- *   of that agreement, and the following does not apply to you.  See the
- *   LICENSE file included with this distribution for more information.
+ * lustre/utils/gss/lgss_keyring.c
  *
- *   If you did not agree to a different license, then this copy of Lustre
- *   is open source software; you can redistribute it and/or modify it
- *   under the terms of version 2 of the GNU General Public License as
- *   published by the Free Software Foundation.
+ * user-space upcall to create GSS context, using keyring interface to kernel
  *
- *   In either case, Lustre is distributed in the hope that it will be
- *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   license text for more details.
+ * Author: Eric Mei <ericm@clusterfs.com>
  */
 
 #include <unistd.h>
@@ -36,8 +50,6 @@
 #include <keyutils.h>
 #include <gssapi/gssapi.h>
 
-#include <libcfs/libcfs.h>
-
 #include "lsupport.h"
 #include "lgss_utils.h"
 #include "write_bytes.h"
@@ -53,6 +65,8 @@ static char *g_service = NULL;
  */
 struct lgss_nego_data {
         uint32_t        lnd_established:1;
+
+        int             lnd_secid;
         uint32_t        lnd_uid;
         uint32_t        lnd_lsvc;
         char           *lnd_uuid;
@@ -82,14 +96,18 @@ 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;
         char            kup_tgt[64];
         char            kup_mech[16];
-        int             kup_is_root;
-        int             kup_is_mds;
+        unsigned int    kup_is_root:1,
+                        kup_is_mdt:1,
+                        kup_is_ost:1;
 };
 
 /****************************************
@@ -118,6 +136,7 @@ int do_nego_rpc(struct lgss_nego_data *lnd,
         }
 
         param.version = GSSD_INTERFACE_VERSION;
+        param.secid = lnd->lnd_secid;
         param.uuid = lnd->lnd_uuid;
         param.lustre_svc = lnd->lnd_lsvc;
         param.uid = lnd->lnd_uid;
@@ -176,15 +195,15 @@ int do_nego_rpc(struct lgss_nego_data *lnd,
         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 %d, token len %d\n",
-               gr->gr_ctx.length, gr->gr_token.length);
-        return 0;
+       logmsg(LL_DEBUG, "do_nego_rpc: receive handle len %d, token len %d, " \
+              "res %d\n", gr->gr_ctx.length, gr->gr_token.length, res);
+       return 0;
 }
 
 /*
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
-int lgssc_negotiation(struct lgss_nego_data *lnd)
+static int lgssc_negotiation(struct lgss_nego_data *lnd)
 {
         struct lgss_init_res    gr;
         gss_buffer_desc        *recv_tokenp, send_token;
@@ -289,15 +308,16 @@ int lgssc_negotiation(struct lgss_nego_data *lnd)
 /*
  * if return error, the lnd_rpc_err or lnd_gss_err is set.
  */
-int lgssc_init_nego_data(struct lgss_nego_data *lnd,
-                         struct keyring_upcall_param *kup,
-                         lgss_mech_t mech)
+static int lgssc_init_nego_data(struct lgss_nego_data *lnd,
+                                struct keyring_upcall_param *kup,
+                                lgss_mech_t 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;
@@ -443,10 +463,10 @@ out:
 }
 
 /*
- * note we can't assume authority in child process
+ * note we inherited assumed authority from parent process
  */
-int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
-                       struct keyring_upcall_param *kup)
+static int lgssc_kr_negotiate(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;
@@ -454,47 +474,28 @@ int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
         int                     rc = -1;
 
         logmsg(LL_TRACE, "child start on behalf of key %08x: "
-               "cred %p, uid %u, svc %u, nid %Lx\n", keyid, cred,
-               cred->lc_uid, cred->lc_tgt_svc, cred->lc_tgt_nid);
-
-        if (kup->kup_gid != 0 && setregid(kup->kup_gid, kup->kup_gid)) {
-                logmsg(LL_WARN, "key %08x, failed set gids to %u: %s\n",
-                       keyid, kup->kup_gid, strerror(errno));
-        }
-
-        if (kup->kup_uid != 0 && setreuid(kup->kup_uid, kup->kup_uid)) {
-                logmsg(LL_WARN, "key %08x, failed set uids to %u: %s\n",
-                       keyid, kup->kup_uid, strerror(errno));
-        }
-
-        /*
-         * link to session keyring, allow the key to be found.
-         */
-        if (keyctl_link(keyid, KEY_SPEC_SESSION_KEYRING)) {
-                logmsg(LL_ERR, "key %08x, failed to link to session "
-                       "keyring: %s\n", keyid, strerror(errno));
-                error_kernel_key(keyid, -EACCES, 0);
-                goto out_cred;
-        }
+               "cred %p, uid %u, svc %u, nid %llx, 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);
 
         if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
                 logmsg(LL_ERR, "key %08x: failed to construct service "
                        "string\n", keyid);
                 error_kernel_key(keyid, -EACCES, 0);
-                goto out_unlink;
+                goto out_cred;
         }
 
         if (lgss_using_cred(cred)) {
                 logmsg(LL_ERR, "key %08x: can't using cred\n", keyid);
                 error_kernel_key(keyid, -EACCES, 0);
-                goto out_unlink;
+                goto out_cred;
         }
 
         if (lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n)) {
                 logmsg(LL_ERR, "key %08x: failed to initialize "
                        "negotiation data\n", keyid);
                 error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
-                goto out_unlink;
+                goto out_cred;
         }
 
         rc = lgssc_negotiation(&lnd);
@@ -524,12 +525,6 @@ out:
 
         lgssc_fini_nego_data(&lnd);
 
-out_unlink:
-        if (keyctl_unlink(keyid, KEY_SPEC_SESSION_KEYRING)) {
-                logmsg(LL_WARN, "failed to unlink key %08x: %s\n",
-                       keyid, strerror(errno));
-        }
-
 out_cred:
         lgss_release_cred(cred);
         return rc;
@@ -537,21 +532,24 @@ out_cred:
 
 /*
  * call out info format: s[:s]...
- *  [0]: mech_name      (string)
- *  [1]: flags          (chars) FMT: r-root; m-mds
- *  [2]: lustre_svc     (uint)
- *  [3]: target_nid     (uint64)
- *  [4]: target_uuid    (string)
+ *  [0]: secid          (uint)
+ *  [1]: mech_name      (string)
+ *  [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)
  */
-static
-int parse_callout_info(const char *coinfo,
-                       struct keyring_upcall_param *uparam)
+static int parse_callout_info(const char *coinfo,
+                              struct keyring_upcall_param *uparam)
 {
-        char    buf[1024];
-        char   *string = buf;
-        int     length, i;
-        char   *data[5];
-        char   *pos;
+        const int       nargs = 8;
+        char            buf[1024];
+        char           *string = buf;
+        int             length, i;
+        char           *data[nargs];
+        char           *pos;
 
         length = strlen(coinfo) + 1;
         if (length > 1024) {
@@ -560,7 +558,7 @@ int parse_callout_info(const char *coinfo,
         }
         memcpy(buf, coinfo, length);
 
-        for (i = 0; i < 4; i++) {
+        for (i = 0; i < nargs - 1; i++) {
                 pos = strchr(string, ':');
                 if (pos == NULL) {
                         logmsg(LL_ERR, "short of components\n");
@@ -573,25 +571,55 @@ int parse_callout_info(const char *coinfo,
         }
         data[i] = string;
 
-        logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s\n",
-               data[0], data[1], data[2], data[3], data[4], data[5]);
+        logmsg(LL_TRACE, "components: %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]);
 
-        strncpy(uparam->kup_mech, data[0], sizeof(uparam->kup_mech));
-        if (strchr(data[1], 'r'))
+        uparam->kup_secid = strtol(data[0], NULL, 0);
+        strncpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
+        uparam->kup_uid = strtol(data[2], NULL, 0);
+        uparam->kup_gid = strtol(data[3], NULL, 0);
+        if (strchr(data[4], 'r'))
                 uparam->kup_is_root = 1;
-        if (strchr(data[1], 'm'))
-                uparam->kup_is_mds = 1;
-        uparam->kup_svc = strtol(data[2], NULL, 0);
-        uparam->kup_nid = strtoll(data[3], NULL, 0);
-        strncpy(uparam->kup_tgt, data[4], sizeof(uparam->kup_tgt));
-
-        logmsg(LL_DEBUG, "parse call out info: mech %s, is_root %d, "
-               "is_mds %d, svc %d, nid 0x%Lx, tgt %s\n",
-               uparam->kup_mech, uparam->kup_is_root, uparam->kup_is_mds,
+        if (strchr(data[4], 'm'))
+                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);
+        strncpy(uparam->kup_tgt, data[7], sizeof(uparam->kup_tgt));
+
+        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%llx, tgt %s\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);
         return 0;
 }
 
+#define LOG_LEVEL_PATH  "/proc/fs/lustre/sptlrpc/gss/lgss_keyring/debug_level"
+
+static void set_log_level()
+{
+        FILE         *file;
+        unsigned int  level;
+
+        file = fopen(LOG_LEVEL_PATH, "r");
+        if (file == NULL)
+                return;
+
+        if (fscanf(file, "%u", &level) != 1)
+                goto out;
+
+        if (level >= LL_MAX)
+                goto out;
+
+        lgss_set_loglevel(level);
+out:
+        fclose(file);
+}
+
 /****************************************
  * main process                         *
  ****************************************/
@@ -606,6 +634,9 @@ int main(int argc, char *argv[])
         struct lgss_mech_type          *mech;
         struct lgss_cred               *cred;
 
+        set_log_level();
+
+        logmsg(LL_TRACE, "start parsing parameters\n");
         /*
          * parse & sanity check upcall parameters
          * expected to be called with:
@@ -625,8 +656,8 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
-        logmsg(LL_INFO, "key %s, desc %s, uid %s, sring %s, coinfo %s\n",
-               argv[2], argv[4], argv[6], argv[10], argv[5]);
+        logmsg(LL_INFO, "key %s, desc %s, ugid %s:%s, sring %s, coinfo %s\n",
+               argv[2], argv[4], argv[6], argv[7], argv[10], argv[5]);
 
         memset(&uparam, 0, sizeof(uparam));
 
@@ -640,11 +671,16 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
-        if (sscanf(argv[6], "%d", &uparam.kup_uid) != 1) {
+        if (sscanf(argv[6], "%d", &uparam.kup_fsuid) != 1) {
                 logmsg(LL_ERR, "can't extract UID: %s\n", argv[6]);
                 return 1;
         }
 
+        if (sscanf(argv[7], "%d", &uparam.kup_fsgid) != 1) {
+                logmsg(LL_ERR, "can't extract GID: %s\n", argv[7]);
+                return 1;
+        }
+
         if (sscanf(argv[10], "%d", &sring) != 1) {
                 logmsg(LL_ERR, "can't extract session keyring: %s\n", argv[10]);
                 return 1;
@@ -681,8 +717,9 @@ int main(int argc, char *argv[])
         }
 
         cred->lc_uid = uparam.kup_uid;
-        cred->lc_fl_root = (uparam.kup_is_root != 0);
-        cred->lc_fl_mds = (uparam.kup_is_mds != 0);
+        cred->lc_root_flags |= uparam.kup_is_root ? LGSS_ROOT_CRED_ROOT : 0;
+        cred->lc_root_flags |= uparam.kup_is_mdt ? LGSS_ROOT_CRED_MDT : 0;
+        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;
 
@@ -692,11 +729,16 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
-        /*
-         * pre initialize the key
+        /* pre initialize the key. note the keyring linked to is actually of the
+         * original requesting process, not _this_ upcall process. if it's for
+         * root user, don't link to any keyrings because we want fully control
+         * on it, and share it among all root sessions; otherswise link to
+         * session keyring.
          */
-        inst_keyring = (cred->lc_fl_root || cred->lc_fl_mds) ?
-                                0 : KEY_SPEC_SESSION_KEYRING;
+        if (cred->lc_root_flags != 0)
+                inst_keyring = 0;
+        else
+                inst_keyring = KEY_SPEC_SESSION_KEYRING;
 
         if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) {
                 logmsg(LL_ERR, "instantiate key %08x: %s\n",