Whamcloud - gitweb
LU-9243 gss: fix GSS struct definition badness
[fs/lustre-release.git] / lustre / utils / gss / lgss_keyring.c
index 9a093ad..f34981c 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/utils/gss/lgss_keyring.c
  *
@@ -53,6 +52,7 @@
 
 #include <libcfs/util/param.h>
 #include <libcfs/util/string.h>
+#include <uapi/linux/lustre/lgss.h>
 #include "lsupport.h"
 #include "lgss_utils.h"
 #include "write_bytes.h"
@@ -261,17 +261,8 @@ 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)));
-
-               /* kernel return -ETIMEDOUT means the rpc timedout, we should
-                * notify the caller to reinitiate the gss negotiation, by
-                * returning -ERESTART
-                */
-               if (param.status == -ETIMEDOUT)
-                       rc = -ERESTART;
-               else
-                       rc = param.status;
-               return rc;
+                      (long int)param.status, strerror((int)(-param.status)));
+               return param.status;
        }
 
        p = (unsigned int *)outbuf;
@@ -424,7 +415,7 @@ static int lgssc_negotiation(struct lgss_nego_data *lnd, int req_fd[2],
                        if (lnd->lnd_rpc_err) {
                                logmsg(LL_ERR, "negotiation rpc error: %d\n",
                                       lnd->lnd_rpc_err);
-                               return -1;
+                               return lnd->lnd_rpc_err;
                        }
 
                        if (gr.gr_major != GSS_S_COMPLETE &&
@@ -433,7 +424,7 @@ static int lgssc_negotiation(struct lgss_nego_data *lnd, int req_fd[2],
 
                                logmsg(LL_ERR, "negotiation gss error %x\n",
                                       lnd->lnd_gss_err);
-                               return -1;
+                               return -ENOTCONN;
                        }
 
                        if (gr.gr_ctx.length != 0) {
@@ -646,11 +637,10 @@ static int lgssc_kr_negotiate_krb(key_serial_t keyid, struct lgss_cred *cred,
                                  struct keyring_upcall_param *kup,
                                  int req_fd[2], int reply_fd[2])
 {
-       struct lgss_nego_data   lnd;
-       OM_uint32               min_stat;
-       int                     rc = -1;
-
-       memset(&lnd, 0, sizeof(lnd));
+       struct lgss_nego_data lnd;
+       OM_uint32 min_stat;
+       int rc = -1;
+       bool redo = true;
 
        if (lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid)) {
                logmsg(LL_ERR, "key %08x: failed to construct service "
@@ -665,6 +655,8 @@ static int lgssc_kr_negotiate_krb(key_serial_t keyid, struct lgss_cred *cred,
                goto out_cred;
        }
 
+retry_nego:
+       memset(&lnd, 0, sizeof(lnd));
        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);
@@ -673,7 +665,11 @@ static int lgssc_kr_negotiate_krb(key_serial_t keyid, struct lgss_cred *cred,
        }
 
        rc = lgssc_negotiation(&lnd, req_fd, reply_fd);
-       if (rc) {
+       if (rc == -EAGAIN || (rc == -ETIMEDOUT && redo)) {
+               logmsg(LL_ERR, "Failed negotiation must retry\n");
+               redo = false;
+               goto retry_nego;
+       } else if (rc) {
                logmsg(LL_ERR, "key %08x: failed to negotiation\n", keyid);
                error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
                goto out;
@@ -709,12 +705,10 @@ static int lgssc_kr_negotiate_manual(key_serial_t keyid, struct lgss_cred *cred,
                                     struct keyring_upcall_param *kup,
                                     int req_fd[2], int reply_fd[2])
 {
-       struct lgss_nego_data   lnd;
-       OM_uint32               min_stat;
-       int                     rc;
-
-retry:
-       memset(&lnd, 0, sizeof(lnd));
+       struct lgss_nego_data lnd;
+       OM_uint32 min_stat;
+       int rc;
+       bool redo = true;
 
        rc = lgss_get_service_str(&g_service, kup->kup_svc, kup->kup_nid);
        if (rc) {
@@ -731,6 +725,8 @@ retry:
                goto out_cred;
        }
 
+retry:
+       memset(&lnd, 0, sizeof(lnd));
        rc = lgssc_init_nego_data(&lnd, kup, cred->lc_mech->lmt_mech_n);
        if (rc) {
                logmsg(LL_ERR, "key %08x: failed to initialize "
@@ -745,10 +741,10 @@ retry:
         * update to the kernel key
         */
        rc = lgssc_negotiation_manual(&lnd, cred, req_fd, reply_fd);
-       if (rc == -EAGAIN) {
+       if (rc == -EAGAIN || (rc == -ETIMEDOUT && redo)) {
                logmsg(LL_ERR, "Failed negotiation must retry\n");
+               redo = false;
                goto retry;
-
        } else if (rc) {
                logmsg(LL_ERR, "key %08x: failed to negotiate\n", keyid);
                error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err);
@@ -850,7 +846,7 @@ static int parse_callout_info(const char *coinfo,
               data[6], data[7], data[8], data[9], data[10]);
 
        uparam->kup_secid = strtol(data[0], NULL, 0);
-       strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
+       snprintf(uparam->kup_mech, sizeof(uparam->kup_mech), "%s", data[1]);
        uparam->kup_uid = strtol(data[2], NULL, 0);
        uparam->kup_gid = strtol(data[3], NULL, 0);
        if (strchr(data[4], 'r'))
@@ -862,7 +858,7 @@ static int parse_callout_info(const char *coinfo,
        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));
+       snprintf(uparam->kup_tgt, sizeof(uparam->kup_tgt), "%s", data[8]);
        uparam->kup_selfnid = strtoll(data[9], NULL, 0);
        uparam->kup_pid = strtol(data[10], NULL, 0);
 
@@ -906,7 +902,6 @@ out:
 
 static int associate_with_ns(char *path)
 {
-#ifdef HAVE_SETNS
        int fd, rc = -1;
 
        fd = open(path, O_RDONLY);
@@ -916,9 +911,6 @@ static int associate_with_ns(char *path)
        }
 
        return rc;
-#else
-       return -1;
-#endif /* HAVE_SETNS */
 }
 
 static int prepare_and_instantiate(struct lgss_cred *cred, key_serial_t keyid,
@@ -971,10 +963,8 @@ int main(int argc, char *argv[])
        char                          path[PATH_MAX] = "";
        int                           other_ns = 0;
        int                           rc = 0;
-#ifdef HAVE_SETNS
        struct stat                   parent_ns = { .st_ino = 0 };
        struct stat                   caller_ns = { .st_ino = 0 };
-#endif
 
        set_log_level();
 
@@ -1068,25 +1058,32 @@ int main(int argc, char *argv[])
        cred->lc_svc_type = uparam.kup_svc_type;
        cred->lc_self_nid = uparam.kup_selfnid;
 
-#ifdef HAVE_SETNS
        /* Is caller in different namespace? */
-       snprintf(path, sizeof(path), "/proc/%d/ns/mnt", getpid());
-       if (stat(path, &parent_ns))
-               logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
-       snprintf(path, sizeof(path), "/proc/%d/ns/mnt", uparam.kup_pid);
-       if (stat(path, &caller_ns))
-               logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
-       if (caller_ns.st_ino != parent_ns.st_ino) {
-               other_ns = 1;
+       /* If passed caller's pid is 0, it means we have to stick
+        * with current namespace.
+        */
+       if (uparam.kup_pid) {
+               snprintf(path, sizeof(path), "/proc/%d/ns/mnt", getpid());
+               if (stat(path, &parent_ns)) {
+                       logmsg(LL_DEBUG, "cannot stat %s: %s\n",
+                              path, strerror(errno));
+               } else {
+                       snprintf(path, sizeof(path), "/proc/%d/ns/mnt",
+                                uparam.kup_pid);
+                       if (stat(path, &caller_ns))
+                               logmsg(LL_DEBUG, "cannot stat %s: %s\n",
+                                      path, strerror(errno));
+                       else if (caller_ns.st_ino != parent_ns.st_ino)
+                               other_ns = 1;
+               }
        }
-#endif /* HAVE_SETNS */
 
        /*
         * if caller's namespace is different, fork a child and associate it
         * with caller's namespace to do credentials preparation
         */
        if (other_ns) {
-               logmsg(LL_TRACE, "caller's namespace is diffent\n");
+               logmsg(LL_TRACE, "caller's namespace is different\n");
 
                /* use pipes to pass info between child and parent processes */
                if (pipe(req_fd) == -1) {
@@ -1232,7 +1229,10 @@ out_pipe:
                close(reply_fd[1]);
                return rc;
        } else {
-               logmsg(LL_TRACE, "caller's namespace is the same\n");
+               if (uparam.kup_pid)
+                       logmsg(LL_TRACE, "caller's namespace is the same\n");
+               else
+                       logmsg(LL_TRACE, "stick with current namespace\n");
 
                rc = prepare_and_instantiate(cred, keyid, uparam.kup_uid);
                if (rc != 0)