1 /*
2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3  */
4 /*
5  * Copyright 1993 by OpenVision Technologies, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software
8  * and its documentation for any purpose is hereby granted without fee,
9  * provided that the above copyright notice appears in all copies and
10  * that both that copyright notice and this permission notice appear in
11  * supporting documentation, and that the name of OpenVision not be used
12  * in advertising or publicity pertaining to distribution of the software
13  * without specific, written prior permission. OpenVision makes no
14  * representations about the suitability of this software for any
15  * purpose.  It is provided "as is" without express or implied warranty.
16  *
17  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
21  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  */
25 
26 #include "gssapiP_krb5.h"
27 #include "mglueP.h"  /* SUNW15resync - for KGSS_ macros */
28 
29 /*
30  * $Id: delete_sec_context.c 18396 2006-07-25 20:29:43Z lxs $
31  */
32 
33 
34 #ifdef	 _KERNEL
35 /* SUNW15resync - todo - unify these kernel rel oid funcs with user spc ones */
36 
37 OM_uint32
krb5_gss_internal_release_oid(minor_status,oid)38 krb5_gss_internal_release_oid(minor_status, oid)
39     OM_uint32	*minor_status;
40     gss_OID	*oid;
41 {
42     /*
43      * This function only knows how to release internal OIDs. It will
44      * return GSS_S_CONTINUE_NEEDED for any OIDs it does not recognize.
45      */
46 
47     if ((*oid != gss_mech_krb5) &&
48 	(*oid != gss_mech_krb5_old) &&
49 	(*oid != gss_mech_krb5_wrong) &&
50 	(*oid != gss_nt_krb5_name) &&
51 	(*oid != gss_nt_krb5_principal)) {
52 	/* We don't know about this OID */
53 	return(GSS_S_CONTINUE_NEEDED);
54     }
55     else {
56 	*oid = GSS_C_NO_OID;
57 	*minor_status = 0;
58 	return(GSS_S_COMPLETE);
59     }
60 }
61 
62 OM_uint32
generic_gss_release_oid(minor_status,oid)63 generic_gss_release_oid(minor_status, oid)
64     OM_uint32	*minor_status;
65     gss_OID	*oid;
66 {
67     if (minor_status)
68 	*minor_status = 0;
69 
70     if (*oid == GSS_C_NO_OID)
71 	return(GSS_S_COMPLETE);
72 
73 
74     if ((*oid != GSS_C_NT_USER_NAME) &&
75 	(*oid != GSS_C_NT_MACHINE_UID_NAME) &&
76 	(*oid != GSS_C_NT_STRING_UID_NAME) &&
77 	(*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
78 	(*oid != GSS_C_NT_ANONYMOUS) &&
79 	(*oid != GSS_C_NT_EXPORT_NAME) &&
80 	(*oid != gss_nt_service_name)) {
81 	FREE((*oid)->elements, (*oid)->length);
82 	FREE(*oid, sizeof(gss_OID_desc));
83     }
84     *oid = GSS_C_NO_OID;
85     return(GSS_S_COMPLETE);
86 }
87 
88 OM_uint32
krb5_gss_release_oid(minor_status,oid)89 krb5_gss_release_oid(minor_status, oid)
90     OM_uint32	*minor_status;
91     gss_OID	*oid;
92 {
93 
94     if (krb5_gss_internal_release_oid(minor_status, oid) != GSS_S_COMPLETE) {
95 	/* Pawn it off on the generic routine */
96 	return(generic_gss_release_oid(minor_status, oid));
97     }
98     else {
99 	*oid = GSS_C_NO_OID;
100 	*minor_status = 0;
101 	return(GSS_S_COMPLETE);
102     }
103 }
104 #endif
105 
106 /*ARGSUSED*/
107 OM_uint32
krb5_gss_delete_sec_context(minor_status,context_handle,output_token,gssd_ctx_verifier)108 krb5_gss_delete_sec_context(minor_status,
109 			    context_handle,
110 			    output_token
111 #ifdef	 _KERNEL
112 			    , gssd_ctx_verifier
113 #endif
114 			    )
115      OM_uint32 *minor_status;
116      gss_ctx_id_t *context_handle;
117      gss_buffer_t output_token;
118 #ifdef	 _KERNEL
119      OM_uint32 gssd_ctx_verifier;
120 #endif
121 {
122    krb5_context context;
123    krb5_gss_ctx_id_rec *ctx;
124 
125    if (output_token) {
126       output_token->length = 0;
127       output_token->value = NULL;
128    }
129 
130    /*SUPPRESS 29*/
131    if (*context_handle == GSS_C_NO_CONTEXT) {
132       *minor_status = 0;
133       return(GSS_S_COMPLETE);
134    }
135 
136    /*SUPPRESS 29*/
137    /* validate the context handle */
138    if (! kg_validate_ctx_id(*context_handle)) {
139       *minor_status = (OM_uint32) G_VALIDATE_FAILED;
140       return(GSS_S_NO_CONTEXT);
141    }
142 
143    ctx = (krb5_gss_ctx_id_t) *context_handle;
144    context = ctx->k5_context;
145 
146    /* construct a delete context token if necessary */
147 
148    if (output_token) {
149       OM_uint32 major;
150       gss_buffer_desc empty;
151       empty.length = 0; empty.value = NULL;
152 
153       if ((major = kg_seal(minor_status, *context_handle, 0,
154 			   GSS_C_QOP_DEFAULT,
155 			   &empty, NULL, output_token, KG_TOK_DEL_CTX))) {
156 	 save_error_info(*minor_status, context);
157 	 return(major);
158       }
159    }
160 
161    /* invalidate the context handle */
162 
163    (void)kg_delete_ctx_id(*context_handle);
164 
165    /* free all the context state */
166 
167    if (ctx->seqstate)
168       g_order_free(&(ctx->seqstate));
169 
170    if (ctx->enc)
171       krb5_free_keyblock(context, ctx->enc);
172 
173    if (ctx->seq)
174       krb5_free_keyblock(context, ctx->seq);
175 
176    if (ctx->here)
177       krb5_free_principal(context, ctx->here);
178    if (ctx->there)
179       krb5_free_principal(context, ctx->there);
180    if (ctx->subkey)
181       krb5_free_keyblock(context, ctx->subkey);
182    if (ctx->acceptor_subkey)
183        krb5_free_keyblock(context, ctx->acceptor_subkey);
184 
185    /* We never import the auth_context into the kernel */
186 #ifndef _KERNEL
187    if (ctx->auth_context) {
188        if (ctx->cred_rcache)
189 	   (void)krb5_auth_con_setrcache(context, ctx->auth_context, NULL);
190 
191        krb5_auth_con_free(context, ctx->auth_context);
192    }
193 #endif
194 
195    if (ctx->mech_used)
196        (void) KGSS_RELEASE_OID(minor_status, &ctx->mech_used);
197 
198    if (ctx->authdata)
199 	krb5_free_authdata(context, ctx->authdata);
200 
201    if (ctx->k5_context)
202        krb5_free_context(ctx->k5_context);
203 
204    /* Zero out context */
205    (void) memset(ctx, 0, sizeof(*ctx));
206    xfree_wrap(ctx, sizeof (krb5_gss_ctx_id_rec));
207 
208    /* zero the handle itself */
209 
210    *context_handle = GSS_C_NO_CONTEXT;
211 
212    *minor_status = 0;
213    return(GSS_S_COMPLETE);
214 }
215