]> git.decadent.org.uk Git - nfs-utils.git/blob - support/gssapi/g_accept_sec_context.c
Add gss support from citi @ umich
[nfs-utils.git] / support / gssapi / g_accept_sec_context.c
1 /* #ident  "@(#)gss_accept_sec_context.c 1.19     95/08/07 SMI" */
2
3 /*
4  * Copyright 1996 by Sun Microsystems, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software
7  * and its documentation for any purpose is hereby granted without fee,
8  * provided that the above copyright notice appears in all copies and
9  * that both that copyright notice and this permission notice appear in
10  * supporting documentation, and that the name of Sun Microsystems not be used
11  * in advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission. Sun Microsystems makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 /*
26  *  glue routine for gss_accept_sec_context
27  */
28
29 #include "mglueP.h"
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33 #include <string.h>
34 #include <errno.h>
35
36 OM_uint32 KRB5_CALLCONV
37 gss_accept_sec_context (minor_status,
38                         context_handle,
39                         verifier_cred_handle,
40                         input_token_buffer,
41                         input_chan_bindings,
42                         src_name,
43                         mech_type,
44                         output_token,
45                         ret_flags,
46                         time_rec,
47                         delegated_cred_handle)
48
49 OM_uint32 *             minor_status;
50 gss_ctx_id_t *          context_handle;
51 gss_cred_id_t           verifier_cred_handle;
52 gss_buffer_t            input_token_buffer;
53 gss_channel_bindings_t  input_chan_bindings;
54 gss_name_t *            src_name;
55 gss_OID *               mech_type;
56 gss_buffer_t            output_token;
57 OM_uint32 *             ret_flags;
58 OM_uint32 *             time_rec;
59 gss_cred_id_t *         delegated_cred_handle;
60
61 {
62     OM_uint32           status, temp_status, temp_minor_status;
63     gss_union_ctx_id_t  union_ctx_id;
64     gss_union_cred_t    union_cred;
65     gss_cred_id_t       input_cred_handle = GSS_C_NO_CREDENTIAL;
66     gss_name_t          internal_name;
67     gss_OID_desc        token_mech_type_desc;
68     gss_OID             token_mech_type = &token_mech_type_desc;
69     gss_mechanism       mech;
70
71     gss_initialize();
72
73     if (context_handle == NULL)
74         return GSS_S_NO_CONTEXT;
75
76     /*
77      * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
78      * descriptor to hold the mech type information as well as the
79      * underlying mechanism context handle. Otherwise, cast the
80      * value of *context_handle to the union context variable.
81      */
82
83     if(*context_handle == GSS_C_NO_CONTEXT) {
84
85         /* Get the token mech type */
86         status = __gss_get_mech_type(token_mech_type, input_token_buffer);
87         if (status)
88             return status;
89
90         status = GSS_S_FAILURE;
91         union_ctx_id = (gss_union_ctx_id_t)
92             malloc(sizeof(gss_union_ctx_id_desc));
93         if (!union_ctx_id) {
94             *minor_status = ENOMEM;
95             goto error_out;
96         }
97
98         union_ctx_id->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc));
99         if (!union_ctx_id->mech_type) {
100             *minor_status = ENOMEM;
101             goto error_out;
102         }
103
104         union_ctx_id->mech_type->elements = (void *)
105             malloc(token_mech_type->length);
106         if (!union_ctx_id->mech_type->elements) {
107             *minor_status = ENOMEM;
108             goto error_out;
109         }
110
111         union_ctx_id->mech_type->length = token_mech_type->length;
112         memcpy(union_ctx_id->mech_type->elements,
113                token_mech_type->elements,
114                token_mech_type->length);
115
116         /* copy the supplied context handle */
117
118         union_ctx_id->internal_ctx_id = *context_handle;
119     } else {
120         union_ctx_id = *context_handle;
121         token_mech_type = union_ctx_id->mech_type;
122     }
123
124     /*
125      * get the appropriate cred handle from the union cred struct.
126      * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
127      * use the default credential.
128      */
129     union_cred = (gss_union_cred_t) verifier_cred_handle;
130     input_cred_handle = __gss_get_mechanism_cred(union_cred, token_mech_type);
131
132     /*
133      * now select the approprate underlying mechanism routine and
134      * call it.
135      */
136
137     mech = __gss_get_mechanism (token_mech_type);
138     if (mech && mech->gss_accept_sec_context) {
139
140             status = mech->gss_accept_sec_context(
141 #ifdef USE_MECH_CONTEXT
142                                                   mech->context,
143 #endif
144                                                   minor_status,
145                                                   &union_ctx_id->internal_ctx_id,
146                                                   input_cred_handle,
147                                                   input_token_buffer,
148                                                   input_chan_bindings,
149                                                   &internal_name,
150                                                   mech_type,
151                                                   output_token,
152                                                   ret_flags,
153                                                   time_rec,
154                                                   delegated_cred_handle);
155
156             /* If there's more work to do, keep going... */
157             if (status == GSS_S_CONTINUE_NEEDED)
158                 return GSS_S_CONTINUE_NEEDED;
159
160             /* if the call failed, return with failure */
161             if (status != GSS_S_COMPLETE)
162                 goto error_out;
163
164             /*
165              * if src_name is non-NULL,
166              * convert internal_name into a union name equivalent
167              * First call the mechanism specific display_name()
168              * then call gss_import_name() to create
169              * the union name struct cast to src_name
170              */
171 #if 0
172             /* ANDROS: src_name is never null, it is a ptr from the gss_accept_sec_context
173              * caller.  internal_name may or may not be set by the mechanism. so, don't
174              * call __gss_convert_name_to_union_name which sets the src_name
175              * unless the internal name is set
176              * by the above mech->gss_accept_sec_context.
177              */
178             if (internal_name != NULL && status == GSS_S_COMPLETE) {
179 #else
180             if (src_name != NULL && status == GSS_S_COMPLETE) {
181 #endif
182                 temp_status = __gss_convert_name_to_union_name(
183                        &temp_minor_status, mech, internal_name, src_name);
184                 if (temp_status != GSS_S_COMPLETE) {
185                     if (minor_status)
186                         *minor_status = temp_minor_status;
187                     gss_release_buffer(&temp_minor_status, output_token);
188                     __gss_release_internal_name(&temp_minor_status,
189                                           &mech->mech_type, &internal_name);
190                     return (temp_status);
191                 }
192             }
193
194         if(*context_handle == GSS_C_NO_CONTEXT)
195             *context_handle = (gss_ctx_id_t *) union_ctx_id;
196
197         return(status);
198     }
199
200     return(GSS_S_BAD_MECH);
201
202 error_out:
203     if (union_ctx_id) {
204         if (union_ctx_id->mech_type) {
205             if (union_ctx_id->mech_type->elements)
206                 free(union_ctx_id->mech_type->elements);
207             free(union_ctx_id->mech_type);
208         }
209         free(union_ctx_id);
210     }
211     return (status);
212 }
213