1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * Copyright 1993 by OpenVision Technologies, Inc.
10  *
11  * Permission to use, copy, modify, distribute, and sell this software
12  * and its documentation for any purpose is hereby granted without fee,
13  * provided that the above copyright notice appears in all copies and
14  * that both that copyright notice and this permission notice appear in
15  * supporting documentation, and that the name of OpenVision not be used
16  * in advertising or publicity pertaining to distribution of the software
17  * without specific, written prior permission. OpenVision makes no
18  * representations about the suitability of this software for any
19  * purpose.  It is provided "as is" without express or implied warranty.
20  *
21  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27  * PERFORMANCE OF THIS SOFTWARE.
28  */
29 
30 #include <gssapiP_krb5.h>
31 #include <k5-int.h>
32 
33 OM_uint32
34 krb5_gss_release_cred(ctx, minor_status, cred_handle)
35      void      *ctx;
36      OM_uint32 *minor_status;
37      gss_cred_id_t *cred_handle;
38 {
39     OM_uint32 status;
40 
41     mutex_lock(&krb5_mutex);
42     status = krb5_gss_release_cred_no_lock(ctx, minor_status, cred_handle);
43     mutex_unlock(&krb5_mutex);
44     return(status);
45 }
46 
47 OM_uint32
48 krb5_gss_release_cred_no_lock(ctx, minor_status, cred_handle)
49      void      *ctx;
50      OM_uint32 *minor_status;
51      gss_cred_id_t *cred_handle;
52 {
53    krb5_context context = ctx;
54    krb5_gss_cred_id_t cred;
55    krb5_error_code code1, code2, code3;
56 
57    /* Solaris Kerberos:  for MT safety, we avoid the use of a default
58     * context via kg_get_context() */
59 #if 0
60    if (GSS_ERROR(kg_get_context(minor_status, &context)))
61       return(GSS_S_FAILURE);
62 #endif
63 
64    if (*cred_handle == GSS_C_NO_CREDENTIAL)
65    {
66       /* Solaris Kerberos:  the followin function does nothing */
67       return(kg_release_defcred(minor_status));
68    }
69 
70    if (! kg_delete_cred_id(*cred_handle)) {
71       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
72       return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_NO_CRED);
73    }
74 
75    cred = (krb5_gss_cred_id_t)*cred_handle;
76 
77    if (cred->ccache) {
78       /*
79        * If the ccache is a MEMORY ccache then this credential handle
80        * should be the only way to get to it, at least until the advent
81        * of a GSS_Duplicate_cred() (which is needed and may well be
82        * added some day).  Until then MEMORY ccaches must be destroyed,
83        * not closed, else their contents (tickets, session keys) will
84        * leak.
85        */
86       if (strcmp("MEMORY", krb5_cc_get_type(context, cred->ccache)) == 0)
87          code1 = krb5_cc_destroy(context, cred->ccache);
88       else
89          code1 = krb5_cc_close(context, cred->ccache);
90    } else
91       code1 = 0;
92 
93    if (cred->keytab)
94       code2 = krb5_kt_close(context, cred->keytab);
95    else
96       code2 = 0;
97 
98    if (cred->rcache)
99       code3 = krb5_rc_close(context, cred->rcache);
100    else
101       code3 = 0;
102    if (cred->princ)
103       krb5_free_principal(context, cred->princ);
104    xfree(cred);
105 
106    *cred_handle = NULL;
107 
108    *minor_status = 0;
109    if (code1)
110       *minor_status = code1;
111    if (code2)
112       *minor_status = code2;
113    if (code3)
114       *minor_status = code3;
115 
116    return(*minor_status?GSS_S_FAILURE:GSS_S_COMPLETE);
117 }
118