]> andersk Git - gssapi-openssh.git/blobdiff - openssh/gss-serv-gsi.c
updated patch from Matthieu Hautreux for cascading credentials
[gssapi-openssh.git] / openssh / gss-serv-gsi.c
index d8714e3e8b0621bfa21442e061736958821a9d96..bd72536c895af113d6e6b739bc2f5d1fdb880c0a 100644 (file)
 #ifdef GSSAPI
 #ifdef GSI
 
-#include "auth.h"
-#include "auth-pam.h"
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+
 #include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
 #include "log.h"
 #include "servconf.h"
 
+#include "buffer.h"
 #include "ssh-gss.h"
 
+extern ServerOptions options;
+
 #include <globus_gss_assist.h>
 
+static int ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name);
+static int ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user);
+static void ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client);
+static void ssh_gssapi_gsi_updatecreds(ssh_gssapi_ccache *store,
+                                      ssh_gssapi_client *client);
+
+ssh_gssapi_mech gssapi_gsi_mech = {
+       "dZuIebMjgUqaxvbF7hDbAw==",
+       "GSI",
+       {9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"},
+       NULL,
+       &ssh_gssapi_gsi_userok,
+       &ssh_gssapi_gsi_localname,
+       &ssh_gssapi_gsi_storecreds,
+       &ssh_gssapi_gsi_updatecreds
+};
+
 /*
  * Check if this user is OK to login under GSI. User has been authenticated
  * as identity in global 'client_name.value' and is trying to log in as passed
@@ -48,112 +74,165 @@ static int
 ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name)
 {
     int authorized = 0;
+    globus_result_t res;
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    char lname[256] = "";
+#endif
     
-    /* This returns 0 on success */
-    authorized = (globus_gss_assist_userok(client->name.value,
-                                          name) == 0);
+#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE
+    if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) {
+       return 0;
+    }
+#endif
+
+/* use new globus_gss_assist_map_and_authorize() interface if available */
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    debug("calling globus_gss_assist_map_and_authorize()");
+    if (GLOBUS_SUCCESS !=
+        (res = globus_gss_assist_map_and_authorize(client->context, "ssh",
+                                                   name, lname, 256))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+    } else if (lname && lname[0] && strcmp(name, lname) != 0) {
+        debug("GSI user maps to %s, not %s", lname, name);
+    } else {
+        authorized = 1;
+    }
+#else
+    debug("calling globus_gss_assist_userok()");
+    if (GLOBUS_SUCCESS !=
+        (res = (globus_gss_assist_userok(client->displayname.value,
+                                         name)))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+    } else {
+        authorized = 1;
+    }
+#endif
     
-    debug("GSI user %s is%s authorized as target user %s",
-         (char *) client->name.value,
-         (authorized ? "" : " not"),
-         name);
+    logit("GSI user %s is%s authorized as target user %s",
+       (char *) client->displayname.value, (authorized ? "" : " not"), name);
     
     return authorized;
 }
 
 /*
- * Handle setting up child environment for GSI.
- *
- * Make sure that this is called _after_ we've setuid to the user.
+ * Return the local username associated with the GSI credentials.
+ */
+int
+ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user)
+{
+    globus_result_t res;
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    char lname[256] = "";
+#endif
+
+#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE
+    if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) {
+       return 0;
+    }
+#endif
+
+/* use new globus_gss_assist_map_and_authorize() interface if available */
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    debug("calling globus_gss_assist_map_and_authorize()");
+    if (GLOBUS_SUCCESS !=
+        (res = globus_gss_assist_map_and_authorize(client->context, "ssh",
+                                                   NULL, lname, 256))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+        logit("failed to map GSI user %s", (char *)client->displayname.value);
+        return 0;
+    }
+    *user = strdup(lname);
+#else
+    debug("calling globus_gss_assist_gridmap()");
+    if (GLOBUS_SUCCESS !=
+        (res = globus_gss_assist_gridmap(client->displayname.value, user))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+        logit("failed to map GSI user %s", (char *)client->displayname.value);
+        return 0;
+    }
+#endif
+
+    logit("GSI user %s mapped to target user %s",
+          (char *) client->displayname.value, *user);
+
+    return 1;
+}
+
+/*
+ * Export GSI credentials to disk.
  */
 static void
 ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client)
 {
        OM_uint32       major_status;
        OM_uint32       minor_status;
+       gss_buffer_desc export_cred = GSS_C_EMPTY_BUFFER;
+       char *          p;
        
+       if (!client || !client->creds) {
+           return;
+       }
+
+       major_status = gss_export_cred(&minor_status,
+                                      client->creds,
+                                      GSS_C_NO_OID,
+                                      1,
+                                      &export_cred);
+       if (GSS_ERROR(major_status) && major_status != GSS_S_UNAVAILABLE) {
+           Gssctxt *ctx;
+           ssh_gssapi_build_ctx(&ctx);
+           ctx->major = major_status;
+           ctx->minor = minor_status;
+           ssh_gssapi_set_oid(ctx, &gssapi_gsi_mech.oid);
+           ssh_gssapi_error(ctx);
+           ssh_gssapi_delete_ctx(&ctx);
+           return;
+       }
        
-       if (client->creds != NULL)
-       {
-               char *creds_env = NULL;
-
-               /*
-               * This is the current hack with the GSI gssapi library to
-               * export credentials to disk.
-               */
-
-               debug("Exporting delegated credentials");
-               
-               minor_status = 0xdee0;  /* Magic value */
-               major_status =
-                       gss_inquire_cred(&minor_status,
-                                       client->creds,
-                                       (gss_name_t *) &creds_env,
-                                       NULL,
-                                       NULL,
-                                       NULL);
-
-               if ((major_status == GSS_S_COMPLETE) &&
-                   (minor_status == 0xdee1) &&
-                   (creds_env != NULL))
-               {
-                       char            *value;
-                               
-                       /*
-                       * String is of the form:
-                       * X509_USER_DELEG_PROXY=filename
-                       * so we parse out the filename
-                       * and then set X509_USER_PROXY
-                       * to point at it.
-                       */
-                       value = strchr(creds_env, '=');
-                       
-                       if (value != NULL)
-                       {
-                               *value = '\0';
-                               value++;
+       p = strchr((char *) export_cred.value, '=');
+       if (p == NULL) {
+           logit("Failed to parse exported credentials string '%.100s'",
+               (char *)export_cred.value);
+           gss_release_buffer(&minor_status, &export_cred);
+           return;
+       }
+       *p++ = '\0';
+       if (strcmp((char *)export_cred.value,"X509_USER_DELEG_PROXY") == 0) {
+           client->store.envvar = strdup("X509_USER_PROXY");
+       } else {
+           client->store.envvar = strdup((char *)export_cred.value);
+       }
+       if (access(p, R_OK) == 0) {
+        if (client->store.filename) {
+            if (rename(p, client->store.filename) < 0) {
+                logit("Failed to rename %s to %s: %s", p,
+                      client->store.filename, strerror(errno));
+                xfree(client->store.filename);
+                client->store.filename = strdup(p);
+            } else {
+                p = client->store.filename;
+            }
+        } else {
+            client->store.filename = strdup(p);
+        }
+       }
+       client->store.envval = strdup(p);
 #ifdef USE_PAM
-                               do_pam_putenv("X509_USER_PROXY",value);
+       if (options.use_pam)
+           do_pam_putenv(client->store.envvar, client->store.envval);
 #endif
-                               client->store.filename=NULL;
-                               client->store.envvar="X509_USER_PROXY";
-                               client->store.envval=strdup(value);
-
-                               return;
-                       }
-                       else
-                       {
-                               log("Failed to parse delegated credentials string '%s'",
-                                   creds_env);
-                       }
-               }
-               else
-               {
-                       log("Failed to export delegated credentials (error %ld)",
-                           major_status);
-               }
-       }       
+       gss_release_buffer(&minor_status, &export_cred);
 }
 
-ssh_gssapi_mech gssapi_gsi_mech_old = {
-       "N3+k7/4wGxHyuP8Yxi4RhA==",
-       "GSI",
-       {9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"}
-       NULL,
-       &ssh_gssapi_gsi_userok,
-       NULL,
-       &ssh_gssapi_gsi_storecreds
-};
-
-ssh_gssapi_mech gssapi_gsi_mech = {
-       "dZuIebMjgUqaxvbF7hDbAw==",
-       "GSI",
-       {9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"}
-       NULL,
-       &ssh_gssapi_gsi_userok,
-       NULL,
-       &ssh_gssapi_gsi_storecreds
-};
+/*
+ * Export updated GSI credentials to disk.
+ */
+static int
+ssh_gssapi_gsi_updatecreds(ssh_gssapi_ccache *store,ssh_gssapi_client *client)
+{
+       ssh_gssapi_gsi_storecreds(client);
+       return 1;
+}
 
 #endif /* GSI */
 #endif /* GSSAPI */
This page took 0.092068 seconds and 4 git commands to generate.