xref: /illumos-gate/usr/src/lib/libgss/g_init_sec_context.c (revision e7cbe64f7a72dae5cb44f100db60ca88f3313c65)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *  glue routine for gss_init_sec_context
31  */
32 #include <mechglueP.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 OM_uint32
38 gss_init_sec_context(minor_status,
39 			claimant_cred_handle,
40 			context_handle,
41 			target_name,
42 			req_mech_type,
43 			req_flags,
44 			time_req,
45 			input_chan_bindings,
46 			input_token,
47 			actual_mech_type,
48 			output_token,
49 			ret_flags,
50 			time_rec)
51 
52 OM_uint32 *			minor_status;
53 const gss_cred_id_t		claimant_cred_handle;
54 gss_ctx_id_t 			*context_handle;
55 const gss_name_t		target_name;
56 const gss_OID			req_mech_type;
57 OM_uint32			req_flags;
58 OM_uint32			time_req;
59 const gss_channel_bindings_t	input_chan_bindings;
60 const gss_buffer_t		input_token;
61 gss_OID *			actual_mech_type;
62 gss_buffer_t			output_token;
63 OM_uint32 *			ret_flags;
64 OM_uint32 *			time_rec;
65 
66 {
67 	OM_uint32		status, temp_minor_status;
68 	gss_union_name_t	union_name;
69 	gss_union_cred_t	union_cred;
70 	gss_name_t		internal_name;
71 	gss_union_ctx_id_t	union_ctx_id;
72 	gss_OID			mech_type = GSS_C_NULL_OID;
73 	gss_mechanism		mech;
74 	gss_cred_id_t		input_cred_handle;
75 
76 	if (minor_status == NULL)
77 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
78 	*minor_status = 0;
79 
80 	/* clear output values */
81 	if (actual_mech_type)
82 		*actual_mech_type = NULL;
83 
84 	if (context_handle == NULL)
85 		return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
86 
87 	if (target_name == NULL)
88 		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
89 
90 	if (output_token == NULL)
91 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
92 
93 	output_token->value = NULL;
94 	output_token->length = 0;
95 
96 
97 	if (req_mech_type)
98 		mech_type = (gss_OID)req_mech_type;
99 
100 	union_name = (gss_union_name_t)target_name;
101 
102 	/*
103 	 * obtain the gss mechanism information for the requested
104 	 * mechanism.  If mech_type is NULL, set it to the resultant
105 	 * mechanism
106 	 */
107 	mech = __gss_get_mechanism(mech_type);
108 	if (mech == NULL)
109 		return (GSS_S_BAD_MECH);
110 
111 	if (mech->gss_init_sec_context == NULL)
112 		return (GSS_S_UNAVAILABLE);
113 
114 	if (mech_type == GSS_C_NULL_OID)
115 		mech_type = &mech->mech_type;
116 
117 	/*
118 	 * If target_name is mechanism_specific, then it must match the
119 	 * mech_type that we're about to use.  Otherwise, do an import on
120 	 * the external_name form of the target name.
121 	 */
122 	if (union_name->mech_type &&
123 			g_OID_equal(union_name->mech_type, mech_type)) {
124 		internal_name = union_name->mech_name;
125 	} else {
126 		if ((status = __gss_import_internal_name(minor_status,
127 					mech_type, union_name,
128 					&internal_name)) != GSS_S_COMPLETE)
129 			return (status);
130 	}
131 
132 	/*
133 	 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
134 	 * descriptor to hold the mech type information as well as the
135 	 * underlying mechanism context handle. Otherwise, cast the
136 	 * value of *context_handle to the union context variable.
137 	 */
138 	if (*context_handle == GSS_C_NO_CONTEXT) {
139 		status = GSS_S_FAILURE;
140 		union_ctx_id = (gss_union_ctx_id_t)
141 			malloc(sizeof (gss_union_ctx_id_desc));
142 		if (union_ctx_id == NULL)
143 			goto end;
144 
145 		if (generic_gss_copy_oid(&temp_minor_status, mech_type,
146 				&union_ctx_id->mech_type) != GSS_S_COMPLETE) {
147 			free(union_ctx_id);
148 			goto end;
149 		}
150 
151 		/* copy the supplied context handle */
152 		union_ctx_id->internal_ctx_id = *context_handle;
153 	} else
154 		union_ctx_id = (gss_union_ctx_id_t)*context_handle;
155 
156 	/*
157 	 * get the appropriate cred handle from the union cred struct.
158 	 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
159 	 * use the default credential.
160 	 */
161 	union_cred = (gss_union_cred_t)claimant_cred_handle;
162 	input_cred_handle = __gss_get_mechanism_cred(union_cred, mech_type);
163 
164 	/*
165 	 * now call the approprate underlying mechanism routine
166 	 */
167 
168 	status = mech->gss_init_sec_context(
169 				mech->context,
170 				minor_status,
171 				input_cred_handle,
172 				&union_ctx_id->internal_ctx_id,
173 				internal_name,
174 				mech_type,
175 				req_flags,
176 				time_req,
177 				input_chan_bindings,
178 				input_token,
179 				actual_mech_type,
180 				output_token,
181 				ret_flags,
182 				time_rec);
183 
184 	if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
185 		/*
186 		 * the spec says (the preferred) method is to delete all
187 		 * context info on the first call to init, and on all
188 		 * subsequent calls make the caller responsible for
189 		 * calling gss_delete_sec_context
190 		 */
191 		if (*context_handle == GSS_C_NO_CONTEXT) {
192 			free(union_ctx_id->mech_type->elements);
193 			free(union_ctx_id->mech_type);
194 			free(union_ctx_id);
195 		}
196 	} else if (*context_handle == GSS_C_NO_CONTEXT)
197 		*context_handle = (gss_ctx_id_t)union_ctx_id;
198 
199 end:
200 	if (union_name->mech_name == NULL ||
201 		union_name->mech_name != internal_name) {
202 		(void) __gss_release_internal_name(&temp_minor_status,
203 					mech_type, &internal_name);
204 	}
205 
206 	return (status);
207 }
208