8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / gss_mechs / mech_dh / backend / mech / context.c
blobc1ae0008a552fabf5cb159a4960457aa153eb79b
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/note.h>
31 #include "dh_gssapi.h"
34 * This module contains the implementation of the gssapi context support
35 * routines for the Diffie-Hellman mechanism.
37 * The GSS routines that are supported by this module are:
38 * gss_context_time
39 * gss_delete_sec_context
40 * gss_inquire_context
41 * gss_wrap_size_limit
43 * The following routines are not supported for the Diffie-Hellman
44 * Mechanism at this time.
45 * gss_export_sec_context
46 * gss_import_sec_context
48 * The following routine is not supported since it is obsolete in version 2
49 * of the GSS-API.
50 * gss_process_context_token.
52 * Note that support for gss_init_sec_context and gss_accept_sec_context is
53 * found in context_establish.c
56 OM_uint32
57 __dh_gss_context_time(void *ctx, /* Mechanism context (not used) */
58 OM_uint32 * minor, /* GSS minor status */
59 gss_ctx_id_t context, /* GSS context handle */
60 OM_uint32* time_remaining /* Time remaining */)
63 _NOTE(ARGUNUSED(ctx))
64 /* Context is a dh context */
65 dh_gss_context_t cntx = (dh_gss_context_t)context;
66 time_t now = time(0);
68 if (minor == 0)
69 return (GSS_S_CALL_INACCESSIBLE_WRITE);
71 if (time_remaining == 0)
72 return (GSS_S_CALL_INACCESSIBLE_WRITE);
74 /* Validate context */
75 if ((*minor = __dh_validate_context(cntx)) != DH_SUCCESS)
76 return (GSS_S_NO_CONTEXT);
78 /* See if it is always valid */
79 if (cntx->expire == (time_t)GSS_C_INDEFINITE) {
80 *time_remaining = GSS_C_INDEFINITE;
81 return (GSS_S_COMPLETE);
84 /* Calculate the remainning time */
85 *time_remaining = (now < cntx->expire) ? cntx->expire - now : 0;
87 /* Return expired if there is no time left */
88 return (*time_remaining ? GSS_S_COMPLETE : GSS_S_CONTEXT_EXPIRED);
92 * Delete a Diffie-Hellman context that is pointed to by context.
93 * On a successfull return *context will be NULL.
96 OM_uint32
97 __dh_gss_delete_sec_context(void *ctx, /* Mechanism context */
98 OM_uint32 *minor, /* Mechanism status */
99 gss_ctx_id_t *context, /* GSS context */
100 gss_buffer_t token /* GSS token */)
102 _NOTE(ARGUNUSED(ctx))
104 dh_gss_context_t cntx;
106 if (context == 0)
107 return (GSS_S_CALL_INACCESSIBLE_READ |
108 GSS_S_CALL_INACCESSIBLE_WRITE);
110 /* context is a Diffie-Hellman context */
111 cntx = (dh_gss_context_t)*context;
113 if (minor == 0)
114 return (GSS_S_CALL_INACCESSIBLE_WRITE);
117 * If token then set the length to zero value to zero to indicate
118 * We indicat a null token since we don't need to send a token to
119 * the other side.
122 if (token) {
123 token->length = 0;
124 token->value = NULL;
127 /* Deleting a null context is OK */
128 if (cntx == NULL)
129 return (GSS_S_COMPLETE);
131 /* Validate the context */
132 if ((*minor = __dh_validate_context(cntx)) != DH_SUCCESS)
133 return (GSS_S_NO_CONTEXT);
135 /* Zero out the session keys! */
136 memset(cntx->keys, 0, cntx->no_keys * sizeof (des_block));
138 /* Unregister the context */
139 *minor = __dh_remove_context(cntx);
141 /* Free storage */
142 __dh_destroy_seq_hist(cntx);
143 free(cntx->remote);
144 free(cntx->local);
145 Free(cntx->keys);
146 Free(cntx);
148 /* Set context to NULL */
149 *context = NULL;
151 return (GSS_S_COMPLETE);
156 * Diffie-Hellman mechanism currently does not support exporting and importing
157 * gss contexts.
160 OM_uint32
161 /*ARGSUSED*/
162 __dh_gss_export_sec_context(void *ctx, OM_uint32 *minor,
163 gss_ctx_id_t *context, gss_buffer_t token)
165 return (GSS_S_UNAVAILABLE);
168 OM_uint32
169 /*ARGSUSED*/
170 __dh_gss_import_sec_context(void * ctx, OM_uint32 *minor,
171 gss_buffer_t token, gss_ctx_id_t *context)
173 return (GSS_S_UNAVAILABLE);
177 * Get the state of a Diffie-Hellman context
180 OM_uint32
181 __dh_gss_inquire_context(void *ctx, /* Mechanism context */
182 OM_uint32 *minor, /* Mechanism status */
183 gss_ctx_id_t context, /* GSS context */
184 gss_name_t *initiator, /* Name of initiator */
185 gss_name_t *acceptor, /* Name of acceptor */
186 OM_uint32 *time_rec, /* Amount of time left */
187 gss_OID *mech, /* return OID of mechanism */
188 OM_uint32 *flags_rec, /* flags set on context */
189 int *local, /* True if we're the initiator */
190 int *open /* True if the context is established */)
192 dh_gss_context_t cntx;
193 OM_uint32 stat = GSS_S_COMPLETE;
194 OM_uint32 t;
196 /* context is a Diffie-Hellman */
197 cntx = (dh_gss_context_t)context;
199 /* Validate the context */
200 if ((*minor = __dh_validate_context(cntx)) != DH_SUCCESS)
201 return (GSS_S_NO_CONTEXT);
203 /* If the caller wants the mechanism OID set *mech to if we can */
204 if (mech) {
205 if (ctx == 0) {
206 *mech = GSS_C_NO_OID;
207 return (GSS_S_CALL_INACCESSIBLE_READ);
209 else
210 *mech = ((dh_context_t)ctx)->mech;
213 /* set t to be the time left on the context */
214 if (cntx->expire == GSS_C_INDEFINITE)
215 t = GSS_C_INDEFINITE;
216 else {
217 time_t now = time(0);
218 t = now > cntx->expire ? 0 : (OM_uint32)(cntx->expire - now);
221 /* If the caller wants the initiator set *initiator to it. */
222 if (initiator) {
223 dh_principal p = cntx->initiate ? cntx->local : cntx->remote;
224 *initiator = (gss_name_t)strdup(p);
227 /* If the callers wants the acceptor set *acceptor to it. */
228 if (acceptor) {
229 dh_principal p = cntx->initiate ? cntx->remote : cntx->local;
230 *acceptor = (gss_name_t)strdup(p);
233 /* If the caller wants the time remaining set *time_rec to t */
234 if (time_rec)
235 *time_rec = t;
238 /* Return the flags in flags_rec if set */
239 if (flags_rec)
240 *flags_rec = cntx->flags;
242 /* ditto for local */
243 if (local)
244 *local = cntx->initiate;
246 /* ditto for open */
247 if (open)
248 *open = (cntx->state == ESTABLISHED);
251 /* return GSS_S_CONTEXT_EXPIRED if no time is left on the context */
252 return ((t == 0 ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE) | stat);
256 * __dh_gss_process_context_token.
257 * This routine is not implemented. It is depricated in version 2.
260 OM_uint32
261 /*ARGSUSED*/
262 __dh_gss_process_context_token(void *ctx, OM_uint32 *minor,
263 gss_ctx_id_t context, gss_buffer_t token)
265 return (GSS_S_UNAVAILABLE);
269 * This implements the gss_wrap_size_limit entry point for Diffie-Hellman
270 * mechanism. See RFC 2078 for details. The idea here is for a context,
271 * qop, whether confidentiality is specified, and an output size, return
272 * the maximum input size that will fit in the given output size. Typically
273 * the output size would be the MTU of the higher level protocol using the
274 * GSS-API.
277 OM_uint32
278 __dh_gss_wrap_size_limit(void *ctx, /* Mechanism context (not used) */
279 OM_uint32 *minor, /* Mechanism status */
280 gss_ctx_id_t context, /* GSS context handle */
281 int conf_req, /* True if confidentiality is wanted */
282 gss_qop_t qop_req, /* Requested QOP */
283 OM_uint32 output_size, /* The maximum ouput size */
284 OM_uint32 *input_size /* Input size returned */)
286 _NOTE(ARGUNUSED(ctx))
287 OM_uint32 major, stat = GSS_S_COMPLETE;
288 unsigned int msgsize, sigsize, pad = 1, size;
289 dh_token_desc token;
290 dh_wrap_t wrap = &token.ver.dh_version_u.body.dh_token_body_desc_u.seal;
291 OM_uint32 left;
293 if (input_size == 0)
294 stat = GSS_S_CALL_INACCESSIBLE_WRITE;
296 /* We check for valid unexpired context by calling gss_context_time. */
297 if ((major = stat | __dh_gss_context_time(ctx, minor, context, &left))
298 != GSS_S_COMPLETE)
299 return (major | stat);
301 /* Find the signature size for this qop. */
302 if ((*minor = __get_sig_size(qop_req, &sigsize)) != DH_SUCCESS)
303 return (GSS_S_BAD_QOP | stat);
305 /* Just return if we can't give the caller what it asked for. */
306 if (stat)
307 return (stat);
310 * If we requested confidentiality, get the cipher pad for the
311 * requested qop. Since we can't support privacy the cipher pad
312 * is always 1.
314 if (conf_req)
315 pad = 1;
318 * Set up an empty wrap token to calculate header and signature
319 * overhead.
322 token.ver.verno = DH_PROTO_VERSION;
323 token.ver.dh_version_u.body.type = DH_WRAP;
324 wrap->mic.qop = qop_req;
325 wrap->mic.seqnum = 0;
326 wrap->mic.client_flag = 0;
327 wrap->body.body_len = 0;
328 wrap->body.body_val = 0;
329 token.verifier.dh_signature_len = sigsize;
330 token.verifier.dh_signature_val = 0;
332 /* This is the size of an empy wrap token */
333 size = xdr_sizeof((xdrproc_t)xdr_dh_token_desc, (void *)&token);
335 /* This is the amount of space left to put our message. */
336 msgsize = (output_size > size) ? output_size - size : 0;
338 /* XDR needs to pad to a four byte boundry */
339 msgsize = (msgsize / 4) * 4;
341 /* We need to pad to pad bytes for encryption (=1 if conf_req = 0) */
342 msgsize = (msgsize / pad) * pad;
345 * The serialization of the inner message includes
346 * the original length.
349 msgsize = (msgsize > sizeof (uint_t)) ? msgsize - sizeof (uint_t) : 0;
352 * We now have the space for the inner wrap message, which is also
353 * XDR encoded and is padded to a four byte boundry.
356 msgsize = (msgsize / 4) * 4;
358 *input_size = msgsize;
360 return (GSS_S_COMPLETE);