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
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include "dh_gssapi.h"
33 * This module implements the interfaces for replay and out-of-sequence
37 #define WBITS_DEF 8 * sizeof (seq_word_t) /* Bits in a seq_word_t */
38 static const int WBITS
= WBITS_DEF
; /* Stored in a static int for debuging */
39 static const int NBITS
= SSIZE
* WBITS_DEF
; /* Total bits in the sequence */
42 * The following routines are for debuging:
43 * __context_debug_set_next_seqno
44 * __context_debug_get_next_seqno
45 * __context_debug_set_last_seqno
46 * __context_debug_get_last_seqno
47 * __context_debug_print_seq_hist
48 * __context_debug_get_hist_size
51 * These routines are declared static and there addresses placed into a table.
52 * There is one publicly declare routine __context_debug_entry that is used
53 * to fetch these entries. This way other routines can be added with out
54 * changing the map-version file. This is being done for use with a libgss
55 * test driver. In particular this technique is being used to implement
56 * a pseudo libgss entry point gss_context_cntrl. Its declaration is
58 * gss_context_cntl(OM_uint32 *minor, gss_ctx_id_t ctx, int cmd, void *argp);
60 * Hence the declaratin of the debug routines below.
63 /* Set the next sequence number to be sent */
65 __context_debug_set_next_seqno(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
67 dh_gss_context_t ctx
= (dh_gss_context_t
)cntx
;
68 OM_uint32 seqno
= (OM_uint32
)(intptr_t)argp
;
71 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
75 * If context, set the sequence number.
76 * Locking should not be necessary since OM_uint32 should be atomic
80 mutex_lock(&ctx
->seqno_lock
);
81 ctx
->next_seqno
= seqno
;
82 mutex_unlock(&ctx
->seqno_lock
);
84 return (GSS_S_COMPLETE
);
87 /* Get the next sequence number to be sent */
89 __context_debug_get_next_seqno(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
91 dh_gss_context_t ctx
= (dh_gss_context_t
)cntx
;
94 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
97 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
100 /* Grap the next sequence number */
101 *(OM_uint32
*)argp
= ctx
->next_seqno
;
103 return (GSS_S_COMPLETE
);
106 /* Set the last sequence number to was seen */
108 __context_debug_set_last_seqno(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
110 dh_gss_context_t ctx
= (dh_gss_context_t
)cntx
;
111 OM_uint32 seqno
= (OM_uint32
)(intptr_t)argp
;
114 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
119 * If context, set the sequence number.
120 * Locking should not be necessary since OM_uint32 should be atomic
124 mutex_lock(&ctx
->hist
.seq_arr_lock
);
125 ctx
->hist
.seqno
= seqno
;
126 mutex_unlock(&ctx
->hist
.seq_arr_lock
);
128 return (GSS_S_COMPLETE
);
131 /* Get the last sequence number seen */
133 __context_debug_get_last_seqno(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
135 dh_gss_context_t ctx
= (dh_gss_context_t
)cntx
;
138 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
141 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
144 /* Grap the next sequence number */
145 *(OM_uint32
*)argp
= ctx
->hist
.seqno
;
147 return (GSS_S_COMPLETE
);
156 for (i
= 0; i
< WBITS
; i
++)
157 if (r
& ((seq_word_t
)1 << i
))
158 t
|= ((seq_word_t
)1 << (WBITS
- 1 - i
));
163 /* Print out the sequence history to stderr */
165 __context_debug_print_seq_hist(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
167 _NOTE(ARGUNUSED(argp
))
168 dh_gss_context_t ctx
= (dh_gss_context_t
)cntx
;
172 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
176 /* Print out the sequence history */
177 fprintf(stderr
, "%u: ", ctx
->hist
.seqno
);
179 for (i
= 0; i
< SSIZE
; i
++)
180 fprintf(stderr
, "%016.16llx", rev(ctx
->hist
.arr
[i
]));
181 fprintf(stderr
, "\n");
183 return (GSS_S_COMPLETE
);
186 /* Fetch the size of the history */
188 __context_debug_get_hist_size(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
190 _NOTE(ARGUNUSED(cntx
))
193 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
195 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
198 *(OM_uint32
*)argp
= NBITS
;
200 return (GSS_S_COMPLETE
);
203 /* Set the debug flag on the context */
205 __context_debug(OM_uint32
*minor
, gss_ctx_id_t cntx
, void *argp
)
207 dh_gss_context_t ctx
= (dh_gss_context_t
)cntx
;
210 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
213 ctx
->debug
= (OM_uint32
)(intptr_t)argp
;
215 return (GSS_S_COMPLETE
);
218 /* Type to descript debug routines */
219 typedef OM_uint32 (*fptr
)(OM_uint32
*, gss_ctx_id_t
, void *);
221 /* Array of debug entries defined above */
222 static fptr __context_debug_entry_array
[] = {
224 __context_debug_set_next_seqno
,
225 __context_debug_get_next_seqno
,
226 __context_debug_print_seq_hist
,
227 __context_debug_get_hist_size
,
228 __context_debug_set_last_seqno
,
229 __context_debug_get_last_seqno
232 /* Structure to hold the debug entries */
236 } __context_debug_entry_points
= {
237 sizeof (__context_debug_entry_array
)/sizeof (fptr
),
238 __context_debug_entry_array
242 * Exported entry point for debug routines. A call to this routine will
243 * return a pointer to the above structure.
247 __context_debug_entry()
249 return (&__context_debug_entry_points
);
252 /* *************** End of Debug Section ***************** */
254 /* Clear all the bits in a sequence array */
256 clear_all_bits(seq_array_t sa
)
260 for (i
= 0; i
< SSIZE
; i
++)
261 sa
->arr
[i
] = (seq_word_t
)0;
264 /* Check that a bit is set in a sequence array */
266 check_bit(seq_array_t sa
, unsigned int bit
)
271 return (sa
->arr
[bit
/WBITS
] & ((seq_word_t
)1 << (bit
% WBITS
)) ? 1 : 0);
274 /* Set a bit in a sequence array */
276 set_bit(seq_array_t sa
, unsigned int bit
)
279 sa
->arr
[bit
/WBITS
] |= ((seq_word_t
)1 << (bit
% WBITS
));
282 /* Clear a bit in a sequence array */
284 * This function is not used, but is here as a comment for completeness.
285 * Lint will complain if it is not commented out.
287 * clear_bit(seq_array_t sa, unsigned int bit)
290 * sa->arr[bit/WBITS] &= ~((seq_word_t)1 << (bit % WBITS));
295 * Sift the bits in a sequence array by n
297 * The seqeunece arrays are logically arranged least significant bit to
298 * most significant bit, where the LSB represents that last sequence
299 * number seen. Thus this routine shifts the entire array to the left by
303 * +---------------------------------------------------------------+
305 * +---------------------------------------------------------------+
307 * This bit corresponds to the last sequence number seen sa->seqno.
310 shift_bits(seq_array_t sa
, unsigned int n
)
313 seq_word_t in
= 0, out
;
315 /* How many words to shift */
318 /* Do we need to shift by words */
320 for (i
= SSIZE
- 1; i
>= m
; i
--)
321 sa
->arr
[i
] = sa
->arr
[i
- m
];
323 sa
->arr
[i
] = (seq_word_t
)0;
329 /* The bits we need to shift */
335 for (i
= m
; i
< SSIZE
; i
++) {
336 /* The out going bits */
337 out
= (sa
->arr
[i
] >> (WBITS
- n
));
339 * shift this part of the bit array and "add in"
340 * the most significant bits shifted out of the previous
343 sa
->arr
[i
] = (sa
->arr
[i
] << n
) | in
;
344 /* The output of this word is the input to the next */
351 * See if the given sequence number is out of sequence or is a replay
352 * on the given context. If the context is not interested in either
353 * just return GSS_S_COMPLETE
356 __dh_seq_detection(dh_gss_context_t ctx
, OM_uint32 seqno
)
359 OM_uint32 stat
= GSS_S_COMPLETE
;
363 * See if there is anything to do. If not return with no bits set.
366 if (((ctx
->flags
& GSS_C_REPLAY_FLAG
) == 0) &&
367 ((ctx
->flags
& GSS_C_SEQUENCE_FLAG
) == 0))
370 /* lock the history why we check */
371 mutex_lock(&ctx
->hist
.seq_arr_lock
);
373 /* If debugging print out the current history */
375 __context_debug_print_seq_hist(&minor
, (gss_ctx_id_t
)ctx
, 0);
377 n
= seqno
- ctx
->hist
.seqno
;
378 /* See if n is zero or that the high order bit is set or n = 0 */
379 if ((n
& ~((~((OM_uint32
)0)) >> 1)) || n
== 0) {
380 /* sequence number is in the past */
383 * We want the small piece of the pie, so take the
384 * 2s complement (-n).
388 /* the sequence number is ancient history */
390 stat
= GSS_S_OLD_TOKEN
;
391 /* See if it has been seen before */
392 else if (check_bit(&ctx
->hist
, n
))
393 stat
= GSS_S_DUPLICATE_TOKEN
;
395 /* Otherwise we've seen it now, so recored the fact */
396 set_bit(&ctx
->hist
, n
);
398 /* If we care, report that we're out of sequence */
399 if (ctx
->flags
& GSS_C_SEQUENCE_FLAG
)
400 stat
= GSS_S_UNSEQ_TOKEN
;
403 /* sequence number is in the future so shift */
404 shift_bits(&ctx
->hist
, n
);
406 /* The sequence number is the most recent now */
407 ctx
->hist
.seqno
= seqno
;
409 /* So set the most recent bit */
410 set_bit(&ctx
->hist
, 0);
412 /* if n > 1 and we care report a gap in the sequence */
413 if (n
> 1 && (ctx
->flags
& GSS_C_SEQUENCE_FLAG
))
414 stat
= GSS_S_GAP_TOKEN
;
417 /* If we're debugging print out the new state */
419 __context_debug_print_seq_hist(&minor
, (gss_ctx_id_t
)ctx
, 0);
421 /* Let other threads in */
422 mutex_unlock(&ctx
->hist
.seq_arr_lock
);
424 /* return the status */
429 * Set the next sequence number to use on this context.
430 * Return that sequence number.
433 __dh_next_seqno(dh_gss_context_t ctx
)
437 mutex_lock(&ctx
->seqno_lock
);
438 t
= ctx
->next_seqno
++;
439 mutex_unlock(&ctx
->seqno_lock
);
446 * Initialize sequence history on a new context
449 __dh_init_seq_hist(dh_gss_context_t ctx
)
451 mutex_init(&ctx
->seqno_lock
, USYNC_THREAD
, 0);
453 mutex_init(&ctx
->hist
.seq_arr_lock
, USYNC_THREAD
, 0);
455 clear_all_bits(&ctx
->hist
);
459 * Destroy sequence history on a context.
462 __dh_destroy_seq_hist(dh_gss_context_t ctx
)
465 mutex_destroy(&ctx
->seqno_lock
);
466 mutex_destroy(&ctx
->hist
.seq_arr_lock
);