pull up r24469, r24530, r24533, r24534, r24535, r24537 from trunk
[krb5.git] / src / lib / gssapi / krb5 / set_ccache.c
index 236a83afff14452bbb4c27f2e90de1ced3eb4c9f..4b6c89065f32fbfe748294e12ab073c43a24d4d0 100644 (file)
@@ -1,3 +1,4 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
  * lib/gssapi/krb5/set_ccache.c
  *
@@ -8,7 +9,7 @@
  *   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
 #include <string.h>
 #include "gssapiP_krb5.h"
 
-OM_uint32 KRB5_CALLCONV 
-gss_krb5_ccache_name(minor_status, name, out_name)
-       OM_uint32 *minor_status;
-       const char *name;
-       const char **out_name;
+OM_uint32
+gss_krb5int_ccache_name(OM_uint32 *minor_status,
+                        const gss_OID desired_mech,
+                        const gss_OID desired_object,
+                        gss_buffer_t value)
 {
-       krb5_context context;
-       krb5_error_code retval;
-       static char *oldname = NULL;
-       const char *tmpname = NULL;
+    char *old_name = NULL;
+    OM_uint32 err = 0;
+    OM_uint32 minor = 0;
+    char *gss_out_name;
+    struct krb5_gss_ccache_name_req *req;
+
+    err = gss_krb5int_initialize_library();
+    if (err) {
+        *minor_status = err;
+        return GSS_S_FAILURE;
+    }
+
+    assert(value->length == sizeof(*req));
+
+    if (value->length != sizeof(*req))
+        return GSS_S_FAILURE;
+
+    req = (struct krb5_gss_ccache_name_req *)value->value;
+
+    gss_out_name = k5_getspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
+
+    if (req->out_name) {
+        const char *tmp_name = NULL;
+
+        if (!err) {
+            kg_get_ccache_name (&err, &tmp_name);
+        }
+        if (!err) {
+            old_name = gss_out_name;
+            gss_out_name = (char *)tmp_name;
+        }
+    }
+    /* If out_name was NULL, we keep the same gss_out_name value, and
+       don't free up any storage (leave old_name NULL).  */
+
+    if (!err)
+        kg_set_ccache_name (&err, req->name);
+
+    minor = k5_setspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, gss_out_name);
+    if (minor) {
+        /* Um.  Now what?  */
+        if (err == 0) {
+            err = minor;
+        }
+        free(gss_out_name);
+        gss_out_name = NULL;
+    }
 
-       if (GSS_ERROR(kg_get_context(minor_status, &context)))
-               return (GSS_S_FAILURE);
+    if (!err) {
+        if (req->out_name) {
+            *(req->out_name) = gss_out_name;
+        }
+    }
 
-       if (out_name) {
-               if (oldname != NULL)
-                       free(oldname);
-               /*
-                * Save copy of previous default ccname, since
-                * cc_set_default_name will free it and we don't want
-                * to hang on to a pointer to freed memory.
-                */
-               tmpname = krb5_cc_default_name(context);
-               oldname = malloc(strlen(tmpname) + 1);
-               if (oldname == NULL)
-                       return GSS_S_FAILURE;
-               strcpy(oldname, tmpname);
-               *out_name = oldname;
-       }
+    if (old_name != NULL) {
+        free (old_name);
+    }
 
-       retval = krb5_cc_set_default_name(context, name);
-       if (retval) {
-               *minor_status = retval;
-               return GSS_S_FAILURE;
-       }
-       return GSS_S_COMPLETE;
+    *minor_status = err;
+    return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
 }