4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
27 * A module that implements a dummy security mechanism.
28 * It's mainly used to test GSS-API application. Multiple tokens
29 * exchanged during security context establishment can be
30 * specified through dummy_mech.conf located in /etc.
33 #define dummy_gss_accept_sec_context \
35 #define dummy_gss_acquire_cred \
37 #define dummy_gss_add_cred \
39 #define dummy_gss_compare_name \
41 #define dummy_gss_context_time \
43 #define dummy_gss_delete_sec_context \
45 #define dummy_gss_display_name \
47 #define dummy_gss_display_status \
49 #define dummy_gss_export_sec_context \
51 #define dummy_gss_import_name \
53 #define dummy_gss_import_sec_context \
55 #define dummy_gss_indicate_mechs \
57 #define dummy_gss_init_sec_context \
59 #define dummy_gss_inquire_context \
61 #define dummy_gss_inquire_cred \
63 #define dummy_gss_inquire_cred_by_mech \
65 #define dummy_gss_inquire_names_for_mech \
67 #define dummy_gss_internal_release_oid \
69 #define dummy_gss_process_context_token \
71 #define dummy_gss_release_cred \
73 #define dummy_gss_release_name \
75 #define dummy_gss_seal \
77 #define dummy_gss_sign \
79 #define dummy_gss_unseal \
81 #define dummy_gss_verify \
83 #define dummy_gss_wrap_size_limit \
85 #define dummy_pname_to_uid \
90 #include <gssapiP_dummy.h>
91 #include <mechglueP.h>
92 #include <gssapi_err_generic.h>
94 #define dummy_context_name_len 19
95 /* private routines for dummy_mechanism */
96 static dummy_token_t
make_dummy_token(char *name
);
97 static void free_dummy_token(dummy_token_t
*token
);
98 static gss_buffer_desc
make_dummy_token_buffer(char *name
);
99 static gss_buffer_desc
make_dummy_token_msg(void *data
, int datalen
);
100 static int der_length_size(int length
);
101 static void der_write_length(unsigned char ** buf
, int length
);
102 static int der_read_length(unsigned char **buf
, int *bufsize
);
103 static int g_token_size(gss_OID mech
, unsigned int body_size
);
104 static void g_make_token_header(gss_OID mech
, int body_size
,
105 unsigned char **buf
, int tok_type
);
106 static int g_verify_token_header(gss_OID mech
, int *body_size
,
107 unsigned char **buf_in
, int tok_type
,
111 /* private global variables */
112 static char dummy_srcname
[] = "dummy source";
113 static OM_uint32 dummy_flags
;
114 static int token_nums
;
118 * { iso(1) org(3) internet(6) dod(1) private(4) enterprises(1) sun(42)
119 * products(2) gssapi(26) mechtypes(1) dummy(2) }
121 static struct gss_config dummy_mechanism
=
122 {{10, "\053\006\001\004\001\052\002\032\001\002"},
124 dummy_gss_acquire_cred
,
125 dummy_gss_release_cred
,
126 dummy_gss_init_sec_context
,
127 dummy_gss_accept_sec_context
,
129 dummy_gss_process_context_token
,
130 dummy_gss_delete_sec_context
,
131 dummy_gss_context_time
,
132 dummy_gss_display_status
,
133 dummy_gss_indicate_mechs
,
134 dummy_gss_compare_name
,
135 dummy_gss_display_name
,
136 dummy_gss_import_name
,
137 dummy_gss_release_name
,
138 dummy_gss_inquire_cred
,
141 dummy_gss_export_sec_context
,
142 dummy_gss_import_sec_context
,
143 dummy_gss_inquire_cred_by_mech
,
144 dummy_gss_inquire_names_for_mech
,
145 dummy_gss_inquire_context
,
146 dummy_gss_internal_release_oid
,
147 dummy_gss_wrap_size_limit
,
149 NULL
, /* __gss_userok */
150 NULL
, /* _export name */
153 NULL
, /* _store_cred */
157 gss_mech_initialize(oid
)
162 dprintf("Entering gss_mech_initialize\n");
165 !g_OID_equal(oid
, &dummy_mechanism
.mech_type
)) {
166 fprintf(stderr
, "invalid dummy mechanism oid.\n");
170 fp
= fopen("/etc/dummy_mech_token.conf", "rF");
172 fprintf(stderr
, "dummy_mech.conf is not found.\n");
173 fprintf(stderr
, "Setting number tokens exchanged to 1\n");
176 fscanf(fp
, "%d", &token_nums
);
178 dprintf("dummy_mech.conf is found.\n");
179 dprintf1("Setting number tokens exchanged to %d\n", token_nums
);
183 dummy_flags
= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
185 dummy_flags
= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
188 dprintf("Leaving gss_mech_initialize\n");
189 return (&dummy_mechanism
);
194 dummy_gss_acquire_cred(ctx
, minor_status
, desired_name
, time_req
, desired_mechs
,
195 cred_usage
, output_cred_handle
,
196 actual_mechs
, time_rec
)
198 OM_uint32
*minor_status
;
199 gss_name_t desired_name
;
201 gss_OID_set desired_mechs
;
202 gss_cred_usage_t cred_usage
;
203 gss_cred_id_t
*output_cred_handle
;
204 gss_OID_set
*actual_mechs
;
207 dprintf("Entering dummy_gss_acquire_cred\n");
210 *actual_mechs
= NULL
;
214 *output_cred_handle
= (gss_cred_id_t
)
215 make_dummy_token("dummy_gss_acquire_cred");
216 if (time_rec
) /* user may pass a null pointer */
217 *time_rec
= GSS_C_INDEFINITE
;
219 if (gss_copy_oid_set(minor_status
, gss_mech_set_dummy
,
220 actual_mechs
) == GSS_S_FAILURE
) {
221 return (GSS_S_FAILURE
);
225 dprintf("Leaving dummy_gss_acquire_cred\n");
226 return (GSS_S_COMPLETE
);
231 dummy_gss_release_cred(ctx
, minor_status
, cred_handle
)
233 OM_uint32
*minor_status
;
234 gss_cred_id_t
*cred_handle
;
236 dprintf("Entering dummy_gss_release_cred\n");
238 free_dummy_token((dummy_token_t
*)(cred_handle
));
241 dprintf("Leaving dummy_gss_release_cred\n");
242 return (GSS_S_COMPLETE
);
247 dummy_gss_init_sec_context(ct
, minor_status
, claimant_cred_handle
,
248 context_handle
, target_name
, mech_type
,
249 req_flags
, time_req
, input_chan_bindings
,
250 input_token
, actual_mech_type
, output_token
,
253 OM_uint32
*minor_status
;
254 gss_cred_id_t claimant_cred_handle
;
255 gss_ctx_id_t
*context_handle
;
256 gss_name_t target_name
;
260 gss_channel_bindings_t input_chan_bindings
;
261 gss_buffer_t input_token
;
262 gss_OID
*actual_mech_type
;
263 gss_buffer_t output_token
;
264 OM_uint32
*ret_flags
;
267 dummy_gss_ctx_id_t ctx
;
268 char token_string
[64];
273 dprintf("Entering init_sec_context\n");
275 output_token
->length
= 0;
276 output_token
->value
= NULL
;
277 if (actual_mech_type
)
278 *actual_mech_type
= NULL
;
280 if (*context_handle
== GSS_C_NO_CONTEXT
) {
282 if (input_token
!= NULL
&& input_token
->value
!= NULL
)
283 return (GSS_S_FAILURE
);
285 ctx
= (dummy_gss_ctx_id_t
)malloc(sizeof (dummy_gss_ctx_id_rec
));
286 ctx
->established
= 0;
287 ctx
->last_stat
= 0xffffffff;
288 *context_handle
= (gss_ctx_id_t
)ctx
;
290 * Initiator interpretation of config file. If 2 or more
291 * the client returns CONTINUE_NNED on the first call.
293 if (token_nums
>= 2) {
294 ret
= GSS_S_CONTINUE_NEEDED
;
296 ret
= GSS_S_COMPLETE
;
304 if (input_token
== NULL
|| input_token
->value
== NULL
) {
305 ctx
->last_stat
= GSS_S_FAILURE
;
306 return (GSS_S_FAILURE
);
309 ctx
= (dummy_gss_ctx_id_t
)(*context_handle
);
312 ptr
= (unsigned char *) input_token
->value
;
313 if (err
= g_verify_token_header((gss_OID
)gss_mech_dummy
,
314 &bodysize
, &ptr
, 0, input_token
->length
)) {
317 ctx
->last_stat
= GSS_S_DEFECTIVE_TOKEN
;
318 return (GSS_S_DEFECTIVE_TOKEN
);
321 if (sscanf((char *)ptr
, "%d", &aret
) < 1) {
323 ctx
->last_stat
= GSS_S_DEFECTIVE_TOKEN
;
324 return (GSS_S_DEFECTIVE_TOKEN
);
327 if (aret
== GSS_S_CONTINUE_NEEDED
) {
328 if (ctx
->last_stat
== GSS_S_COMPLETE
) {
330 * RFC 2078, page 36, under GSS_S_COMPLETE
331 * says that acceptor (target) has sufficient
332 * information to perform per-message
333 * processing. So if initiator previously
334 * returned GSS_S_COMPLETE, and acceptor
335 * says it needs more, then we have
338 ctx
->last_stat
= GSS_S_FAILURE
;
339 return (GSS_S_FAILURE
);
341 ret
= GSS_S_CONTINUE_NEEDED
;
344 ret
= GSS_S_COMPLETE
;
348 if (ret_flags
) /* user may pass a null pointer */
349 *ret_flags
= dummy_flags
;
350 if (time_rec
) /* user may pass a null pointer */
351 *time_rec
= GSS_C_INDEFINITE
;
352 if (actual_mech_type
)
353 *actual_mech_type
= (gss_OID
) gss_mech_dummy
;
355 if (send_token
== 1) {
356 sprintf(token_string
, "%d", ret
);
358 *output_token
= make_dummy_token_msg(
359 token_string
, strlen(token_string
) + 1);
361 *output_token
= make_dummy_token_msg(NULL
, 0);
364 if (ret
== GSS_S_COMPLETE
)
365 ctx
->established
= 1;
367 ctx
->last_stat
= ret
;
373 dummy_gss_accept_sec_context(ct
, minor_status
, context_handle
,
374 verifier_cred_handle
, input_token
,
375 input_chan_bindings
, src_name
, mech_type
,
376 output_token
, ret_flags
, time_rec
,
377 delegated_cred_handle
)
379 OM_uint32
*minor_status
;
380 gss_ctx_id_t
*context_handle
;
381 gss_cred_id_t verifier_cred_handle
;
382 gss_buffer_t input_token
;
383 gss_channel_bindings_t input_chan_bindings
;
384 gss_name_t
*src_name
;
386 gss_buffer_t output_token
;
387 OM_uint32
*ret_flags
;
389 gss_cred_id_t
*delegated_cred_handle
;
391 dummy_gss_ctx_id_t ctx
;
392 char token_string
[64];
393 gss_buffer_desc name
;
400 int return_token
= 0;
402 dprintf("Entering accept_sec_context\n");
405 *src_name
= (gss_name_t
)NULL
;
406 output_token
->length
= 0;
407 output_token
->value
= NULL
;
409 *mech_type
= GSS_C_NULL_OID
;
410 /* return a bogus cred handle */
411 if (delegated_cred_handle
)
412 *delegated_cred_handle
= GSS_C_NO_CREDENTIAL
;
414 /* Check for defective input token. */
415 ptr
= (unsigned char *) input_token
->value
;
416 if (err
= g_verify_token_header((gss_OID
)gss_mech_dummy
, &bodysize
,
418 input_token
->length
)) {
420 return (GSS_S_DEFECTIVE_TOKEN
);
423 if (sscanf((char *)ptr
, "%d", &iret
) < 1) {
425 return (GSS_S_DEFECTIVE_TOKEN
);
428 if (*context_handle
== GSS_C_NO_CONTEXT
) {
429 ctx
= (dummy_gss_ctx_id_t
)malloc(sizeof (dummy_gss_ctx_id_rec
));
430 ctx
->token_number
= token_nums
;
431 ctx
->established
= 0;
432 *context_handle
= (gss_ctx_id_t
)ctx
;
434 ctx
= (dummy_gss_ctx_id_t
)(*context_handle
);
437 if (ret_flags
) /* user may pass a null pointer */
438 *ret_flags
= dummy_flags
;
439 if (time_rec
) /* user may pass a null pointer */
440 *time_rec
= GSS_C_INDEFINITE
;
442 *mech_type
= (gss_OID
)gss_mech_dummy
;
445 * RFC 2078, page 36, under GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED
446 * tells us whether to return a token or not.
449 if (iret
== GSS_S_CONTINUE_NEEDED
)
455 if (ctx
->token_number
> 1) {
457 * RFC 2078, page 36, under GSS_S_COMPLETE, says that if
458 * initiator is done, the target (us) has what it needs, so
459 * it must return GSS_S_COMPLETE;
461 if (iret
== GSS_S_CONTINUE_NEEDED
)
462 status
= GSS_S_CONTINUE_NEEDED
;
464 status
= GSS_S_COMPLETE
;
467 status
= GSS_S_COMPLETE
;
469 /* source name is ready at GSS_S_COMPLELE */
470 if ((status
== GSS_S_COMPLETE
) && src_name
) {
471 name
.length
= strlen(dummy_srcname
);
472 name
.value
= dummy_srcname
;
473 status
= dummy_gss_import_name(ct
, minor_status
, &name
,
474 (gss_OID
)GSS_C_NT_USER_NAME
, &temp
);
475 if (status
!= GSS_S_COMPLETE
) {
476 free(*context_handle
);
477 *context_handle
= GSS_C_NO_CONTEXT
;
483 if (status
== GSS_S_COMPLETE
) {
484 ctx
->established
= 1;
487 if (return_token
== 1) {
488 sprintf(token_string
, "%d", status
);
490 *output_token
= make_dummy_token_msg(
491 token_string
, strlen(token_string
) + 1);
493 *output_token
= make_dummy_token_msg(NULL
, 0);
496 if (ctx
->token_number
> 0)
505 dummy_gss_process_context_token(ct
, minor_status
, context_handle
, token_buffer
)
507 OM_uint32
*minor_status
;
508 gss_ctx_id_t context_handle
;
509 gss_buffer_t token_buffer
;
511 dprintf("In process_sec_context\n");
512 return (GSS_S_COMPLETE
);
517 dummy_gss_delete_sec_context(ct
, minor_status
, context_handle
, output_token
)
519 OM_uint32
*minor_status
;
520 gss_ctx_id_t
*context_handle
;
521 gss_buffer_t output_token
;
523 dummy_gss_ctx_id_t ctx
;
525 dprintf("Entering delete_sec_context\n");
527 /* Make the length to 0, so the output token is not sent to peer */
529 output_token
->length
= 0;
530 output_token
->value
= NULL
;
533 if (*context_handle
== GSS_C_NO_CONTEXT
) {
535 return (GSS_S_COMPLETE
);
538 ctx
= (dummy_gss_ctx_id_t
)*context_handle
;
540 *context_handle
= GSS_C_NO_CONTEXT
;
542 dprintf("Leaving delete_sec_context\n");
543 return (GSS_S_COMPLETE
);
549 dummy_gss_context_time(ct
, minor_status
, context_handle
, time_rec
)
551 OM_uint32
*minor_status
;
552 gss_ctx_id_t context_handle
;
555 dprintf("In context_time\n");
556 if (time_rec
) /* user may pass a null pointer */
557 return (GSS_S_FAILURE
);
559 *time_rec
= GSS_C_INDEFINITE
;
560 return (GSS_S_COMPLETE
);
565 dummy_gss_sign(ctx
, minor_status
, context_handle
,
566 qop_req
, message_buffer
, message_token
)
568 OM_uint32
*minor_status
;
569 gss_ctx_id_t context_handle
;
571 gss_buffer_t message_buffer
;
572 gss_buffer_t message_token
;
574 char token_string
[] = "dummy_gss_sign";
575 dummy_gss_ctx_id_t context
;
577 dprintf("Entering gss_sign\n");
579 context
= (dummy_gss_ctx_id_t
)(context_handle
);
580 if (context_handle
== GSS_C_NO_CONTEXT
)
581 return (GSS_S_NO_CONTEXT
);
582 if (!context
->established
)
583 return (GSS_S_NO_CONTEXT
);
585 *message_token
= make_dummy_token_msg(
586 token_string
, strlen(token_string
));
588 dprintf("Leaving gss_sign\n");
589 return (GSS_S_COMPLETE
);
594 dummy_gss_verify(ctx
, minor_status
, context_handle
,
595 message_buffer
, token_buffer
, qop_state
)
597 OM_uint32
*minor_status
;
598 gss_ctx_id_t context_handle
;
599 gss_buffer_t message_buffer
;
600 gss_buffer_t token_buffer
;
606 dummy_gss_ctx_id_t context
;
608 dprintf("Entering gss_verify\n");
610 context
= (dummy_gss_ctx_id_t
)(context_handle
);
611 if (context_handle
== GSS_C_NO_CONTEXT
)
612 return (GSS_S_NO_CONTEXT
);
613 if (!context
->established
)
614 return (GSS_S_NO_CONTEXT
);
616 /* Check for defective input token. */
617 ptr
= (unsigned char *) token_buffer
->value
;
618 if (err
= g_verify_token_header((gss_OID
)gss_mech_dummy
, &bodysize
,
620 token_buffer
->length
)) {
622 return (GSS_S_DEFECTIVE_TOKEN
);
626 *qop_state
= GSS_C_QOP_DEFAULT
;
628 dprintf("Leaving gss_verify\n");
629 return (GSS_S_COMPLETE
);
634 dummy_gss_seal(ctx
, minor_status
, context_handle
, conf_req_flag
,
635 qop_req
, input_message_buffer
, conf_state
,
636 output_message_buffer
)
638 OM_uint32
*minor_status
;
639 gss_ctx_id_t context_handle
;
642 gss_buffer_t input_message_buffer
;
644 gss_buffer_t output_message_buffer
;
646 gss_buffer_desc output
;
647 dummy_gss_ctx_id_t context
;
649 dprintf("Entering gss_seal\n");
651 context
= (dummy_gss_ctx_id_t
)(context_handle
);
652 if (context_handle
== GSS_C_NO_CONTEXT
)
653 return (GSS_S_NO_CONTEXT
);
654 if (!context
->established
)
655 return (GSS_S_NO_CONTEXT
);
657 /* Copy the input message to output message */
658 output
= make_dummy_token_msg(
659 input_message_buffer
->value
, input_message_buffer
->length
);
664 *output_message_buffer
= output
;
666 dprintf("Leaving gss_seal\n");
667 return (GSS_S_COMPLETE
);
675 dummy_gss_unseal(ctx
, minor_status
, context_handle
,
676 input_message_buffer
, output_message_buffer
,
677 conf_state
, qop_state
)
679 OM_uint32
*minor_status
;
680 gss_ctx_id_t context_handle
;
681 gss_buffer_t input_message_buffer
;
682 gss_buffer_t output_message_buffer
;
686 gss_buffer_desc output
;
690 dummy_gss_ctx_id_t context
;
692 dprintf("Entering gss_unseal\n");
694 context
= (dummy_gss_ctx_id_t
)(context_handle
);
695 if (context_handle
== GSS_C_NO_CONTEXT
)
696 return (GSS_S_NO_CONTEXT
);
697 if (!context
->established
)
698 return (GSS_S_NO_CONTEXT
);
700 ptr
= (unsigned char *) input_message_buffer
->value
;
701 if (err
= g_verify_token_header((gss_OID
)gss_mech_dummy
, &bodysize
,
703 input_message_buffer
->length
)) {
705 return (GSS_S_DEFECTIVE_TOKEN
);
707 output
.length
= bodysize
;
708 output
.value
= (void *)malloc(output
.length
);
709 memcpy(output
.value
, ptr
, output
.length
);
711 *output_message_buffer
= output
;
713 *qop_state
= GSS_C_QOP_DEFAULT
;
717 dprintf("Leaving gss_unseal\n");
718 return (GSS_S_COMPLETE
);
723 dummy_gss_display_status(ctx
, minor_status
, status_value
, status_type
,
724 mech_type
, message_context
, status_string
)
726 OM_uint32
*minor_status
;
727 OM_uint32 status_value
;
730 OM_uint32
*message_context
;
731 gss_buffer_t status_string
;
733 dprintf("Entering display_status\n");
735 *message_context
= 0;
736 *status_string
= make_dummy_token_buffer("dummy_gss_display_status");
738 dprintf("Leaving display_status\n");
739 return (GSS_S_COMPLETE
);
744 dummy_gss_indicate_mechs(ctx
, minor_status
, mech_set
)
746 OM_uint32
*minor_status
;
747 gss_OID_set
*mech_set
;
749 dprintf("Entering indicate_mechs\n");
753 if (gss_copy_oid_set(minor_status
, gss_mech_set_dummy
,
754 mech_set
) == GSS_S_FAILURE
) {
755 return (GSS_S_FAILURE
);
759 dprintf("Leaving indicate_mechs\n");
760 return (GSS_S_COMPLETE
);
765 dummy_gss_compare_name(ctx
, minor_status
, name1
, name2
, name_equal
)
767 OM_uint32
*minor_status
;
772 dummy_name_t name_1
= (dummy_name_t
)name1
;
773 dummy_name_t name_2
= (dummy_name_t
)name2
;
775 dprintf("Entering compare_name\n");
777 if (g_OID_equal(name_1
->type
, name_2
->type
) &&
778 (name_1
->buffer
->length
== name_2
->buffer
->length
) &&
779 !memcmp(name_1
->buffer
->value
, name_2
->buffer
->value
,
780 name_1
->buffer
->length
))
785 dprintf("Leaving compare_name\n");
786 return (GSS_S_COMPLETE
);
791 dummy_gss_display_name(ctx
, minor_status
, input_name
, output_name_buffer
,
794 OM_uint32
*minor_status
;
795 gss_name_t input_name
;
796 gss_buffer_t output_name_buffer
;
797 gss_OID
*output_name_type
;
799 OM_uint32 status
= GSS_S_COMPLETE
;
800 dummy_name_t name
= (dummy_name_t
)input_name
;
802 dprintf("Entering display_name\n");
804 if (g_OID_equal(name
->type
, GSS_C_NT_USER_NAME
) ||
805 g_OID_equal(name
->type
, GSS_C_NT_MACHINE_UID_NAME
) ||
806 g_OID_equal(name
->type
, GSS_C_NT_STRING_UID_NAME
) ||
807 g_OID_equal(name
->type
, GSS_C_NT_HOSTBASED_SERVICE
)) {
809 * output_name_buffer = (gss_buffer_t)
810 * malloc(sizeof (gss_buffer_desc));
812 if (output_name_buffer
== NULL
)
813 return (GSS_S_FAILURE
);
815 output_name_buffer
->length
= name
->buffer
->length
;
816 output_name_buffer
->value
= (void *)
817 malloc(name
->buffer
->length
);
818 if (output_name_buffer
->value
== NULL
)
819 return (GSS_S_FAILURE
);
821 memcpy(output_name_buffer
->value
, name
->buffer
->value
,
822 name
->buffer
->length
);
823 if (output_name_type
)
824 *output_name_type
= name
->type
;
826 dprintf("Leaving display_name\n");
830 dprintf("Leaving display_name\n");
831 return (GSS_S_BAD_NAMETYPE
);
836 dummy_gss_import_name(ctx
, minor_status
, input_name_buffer
,
837 input_name_type
, output_name
)
839 OM_uint32
*minor_status
;
840 gss_buffer_t input_name_buffer
;
841 gss_OID input_name_type
;
842 gss_name_t
*output_name
;
846 dprintf("Entering import_name\n");
851 if (input_name_type
== GSS_C_NULL_OID
)
852 return (GSS_S_BAD_NAMETYPE
);
854 if (g_OID_equal(input_name_type
, GSS_C_NT_USER_NAME
) ||
855 g_OID_equal(input_name_type
, GSS_C_NT_MACHINE_UID_NAME
) ||
856 g_OID_equal(input_name_type
, GSS_C_NT_STRING_UID_NAME
) ||
857 g_OID_equal(input_name_type
, GSS_C_NT_HOSTBASED_SERVICE
)) {
858 dummy_name_t name
= (dummy_name_t
)
859 malloc(sizeof (dummy_name_desc
));
860 name
->buffer
= (gss_buffer_t
)malloc(sizeof (gss_buffer_desc
));
861 name
->buffer
->length
= input_name_buffer
->length
;
862 name
->buffer
->value
= (void *)malloc(input_name_buffer
->length
);
863 if (name
->buffer
->value
== NULL
)
864 return (GSS_S_FAILURE
);
866 memcpy(name
->buffer
->value
, input_name_buffer
->value
,
867 input_name_buffer
->length
);
869 status
= generic_gss_copy_oid(minor_status
,
870 input_name_type
, &(name
->type
));
871 *output_name
= (gss_name_t
)name
;
872 dprintf("Leaving import_name\n");
875 dprintf("Leaving import_name\n");
876 return (GSS_S_BAD_NAMETYPE
);
881 dummy_gss_release_name(ctx
, minor_status
, input_name
)
883 OM_uint32
*minor_status
;
884 gss_name_t
*input_name
;
886 dummy_name_t name
= (dummy_name_t
)*input_name
;
888 dprintf("Entering release_name\n");
889 free(name
->buffer
->value
);
890 generic_gss_release_oid(minor_status
, &(name
->type
));
893 dprintf("Leaving release_name\n");
894 return (GSS_S_COMPLETE
);
899 dummy_gss_inquire_cred(ctx
, minor_status
, cred_handle
, name
, lifetime_ret
,
900 cred_usage
, mechanisms
)
902 OM_uint32
*minor_status
;
903 gss_cred_id_t cred_handle
;
905 OM_uint32
*lifetime_ret
;
906 gss_cred_usage_t
*cred_usage
;
907 gss_OID_set
*mechanisms
;
909 dprintf("Entering inquire_cred\n");
911 *name
= (gss_name_t
)make_dummy_token
912 ("dummy gss credential");
914 *lifetime_ret
= GSS_C_INDEFINITE
;
916 *cred_usage
= GSS_C_BOTH
;
918 if (gss_copy_oid_set(minor_status
, gss_mech_set_dummy
,
919 mechanisms
) == GSS_S_FAILURE
)
920 return (GSS_S_FAILURE
);
923 dprintf("Leaving inquire_cred\n");
924 return (GSS_S_COMPLETE
);
929 dummy_gss_add_cred(ctx
, minor_status
, input_cred_handle
,
930 desired_name
, desired_mech
, cred_usage
,
931 initiator_time_req
, acceptor_time_req
,
932 output_cred_handle
, actual_mechs
,
933 initiator_time_rec
, acceptor_time_rec
)
935 OM_uint32
*minor_status
;
936 gss_cred_id_t input_cred_handle
;
937 gss_name_t desired_name
;
938 gss_OID desired_mech
;
939 gss_cred_usage_t cred_usage
;
940 OM_uint32 initiator_time_req
;
941 OM_uint32 acceptor_time_req
;
942 gss_cred_id_t
*output_cred_handle
;
943 gss_OID_set
*actual_mechs
;
944 OM_uint32
*initiator_time_rec
;
945 OM_uint32
*acceptor_time_rec
;
947 dprintf("Entering add_cred\n");
949 if ((desired_mech
!= GSS_C_NULL_OID
) &&
950 (g_OID_equal(desired_mech
, gss_mech_dummy
)))
951 return (GSS_S_BAD_MECH
);
954 dprintf("Leaving add_cred\n");
956 /* This routine likes in kerberos V5 is never be used / called by */
957 /* the GSS_API. It simply returns GSS_S_DUPLICATE_ELEMENT to indicate */
960 return (GSS_S_DUPLICATE_ELEMENT
);
963 /* Should I add the token structure to deal with import/export */
964 /* of sec_context. For now, I just create dummy interprocess token, and when */
965 /* the peer accept it, it calls the import_sec_context.The import_sec_context */
966 /* creates new sec_context with status established. (rather than get it */
967 /* from interprocess token. it can be done because the sec context in dummy */
968 /* mechanism is very simple (contains only status if it's established). */
971 dummy_gss_export_sec_context(ct
, minor_status
, context_handle
,
974 OM_uint32
*minor_status
;
975 gss_ctx_id_t
*context_handle
;
976 gss_buffer_t interprocess_token
;
978 char str
[] = "dummy_gss_export_sec_context";
980 dprintf("Entering export_sec_context\n");
982 *interprocess_token
= make_dummy_token_msg(str
, strlen(str
));
983 free(*context_handle
);
984 *context_handle
= GSS_C_NO_CONTEXT
;
986 dprintf("Leaving export_sec_context\n");
987 return (GSS_S_COMPLETE
);
992 dummy_gss_import_sec_context(ct
, minor_status
, interprocess_token
,
995 OM_uint32
*minor_status
;
996 gss_buffer_t interprocess_token
;
997 gss_ctx_id_t
*context_handle
;
999 /* Assume that we got ctx from the interprocess token. */
1000 dummy_gss_ctx_id_t ctx
;
1002 dprintf("Entering import_sec_context\n");
1004 ctx
= (dummy_gss_ctx_id_t
)malloc(sizeof (dummy_gss_ctx_id_rec
));
1005 ctx
->token_number
= 0;
1006 ctx
->established
= 1;
1008 *context_handle
= (gss_ctx_id_t
)ctx
;
1010 dprintf("Leaving import_sec_context\n");
1011 return (GSS_S_COMPLETE
);
1016 dummy_gss_inquire_cred_by_mech(ctx
, minor_status
, cred_handle
,
1017 mech_type
, name
, initiator_lifetime
,
1018 acceptor_lifetime
, cred_usage
)
1020 OM_uint32
*minor_status
;
1021 gss_cred_id_t cred_handle
;
1024 OM_uint32
*initiator_lifetime
;
1025 OM_uint32
*acceptor_lifetime
;
1026 gss_cred_usage_t
*cred_usage
;
1028 dprintf("Entering inquire_cred_by_mech\n");
1030 *name
= (gss_name_t
)make_dummy_token("dummy credential name");
1031 if (initiator_lifetime
)
1032 *initiator_lifetime
= GSS_C_INDEFINITE
;
1033 if (acceptor_lifetime
)
1034 *acceptor_lifetime
= GSS_C_INDEFINITE
;
1036 *cred_usage
= GSS_C_BOTH
;
1038 dprintf("Leaving inquire_cred_by_mech\n");
1039 return (GSS_S_COMPLETE
);
1044 dummy_gss_inquire_names_for_mech(ctx
, minor_status
, mechanism
, name_types
)
1046 OM_uint32
*minor_status
;
1048 gss_OID_set
*name_types
;
1050 OM_uint32 major
, minor
;
1052 dprintf("Entering inquire_names_for_mech\n");
1054 * We only know how to handle our own mechanism.
1056 if ((mechanism
!= GSS_C_NULL_OID
) &&
1057 !g_OID_equal(gss_mech_dummy
, mechanism
)) {
1059 return (GSS_S_FAILURE
);
1062 major
= gss_create_empty_oid_set(minor_status
, name_types
);
1063 if (major
== GSS_S_COMPLETE
) {
1064 /* Now add our members. */
1065 if (((major
= gss_add_oid_set_member(minor_status
,
1066 (gss_OID
) GSS_C_NT_USER_NAME
, name_types
))
1067 == GSS_S_COMPLETE
) &&
1068 ((major
= gss_add_oid_set_member(minor_status
,
1069 (gss_OID
) GSS_C_NT_MACHINE_UID_NAME
, name_types
))
1070 == GSS_S_COMPLETE
) &&
1071 ((major
= gss_add_oid_set_member(minor_status
,
1072 (gss_OID
) GSS_C_NT_STRING_UID_NAME
, name_types
))
1073 == GSS_S_COMPLETE
)) {
1074 major
= gss_add_oid_set_member(minor_status
,
1075 (gss_OID
) GSS_C_NT_HOSTBASED_SERVICE
, name_types
);
1078 if (major
!= GSS_S_COMPLETE
)
1079 (void) gss_release_oid_set(&minor
, name_types
);
1082 dprintf("Leaving inquire_names_for_mech\n");
1088 dummy_gss_inquire_context(ct
, minor_status
, context_handle
, initiator_name
,
1089 acceptor_name
, lifetime_rec
, mech_type
, ret_flags
,
1090 locally_initiated
, open
)
1092 OM_uint32
*minor_status
;
1093 gss_ctx_id_t context_handle
;
1094 gss_name_t
*initiator_name
;
1095 gss_name_t
*acceptor_name
;
1096 OM_uint32
*lifetime_rec
;
1098 OM_uint32
*ret_flags
;
1099 int *locally_initiated
;
1102 dummy_gss_ctx_id_t ctx
;
1103 dummy_name_t name1
, name2
;
1106 dprintf("Entering inquire_context\n");
1108 ctx
= (dummy_gss_ctx_id_t
)(context_handle
);
1109 name1
= (dummy_name_t
)
1110 malloc(sizeof (dummy_name_desc
));
1111 name1
->buffer
= (gss_buffer_t
)malloc(sizeof (gss_buffer_desc
));
1112 name1
->buffer
->length
= dummy_context_name_len
;
1113 name1
->buffer
->value
= make_dummy_token("dummy context name");
1114 status
= generic_gss_copy_oid(minor_status
,
1115 (gss_OID
) GSS_C_NT_USER_NAME
, &(name1
->type
));
1116 if (status
!= GSS_S_COMPLETE
)
1119 *initiator_name
= (gss_name_t
)name1
;
1121 name2
= (dummy_name_t
)
1122 malloc(sizeof (dummy_name_desc
));
1123 name2
->buffer
= (gss_buffer_t
)malloc(sizeof (gss_buffer_desc
));
1124 name2
->buffer
->length
= dummy_context_name_len
;
1125 name2
->buffer
->value
= make_dummy_token("dummy context name");
1126 status
= generic_gss_copy_oid(minor_status
,
1127 (gss_OID
) GSS_C_NT_USER_NAME
, &(name2
->type
));
1128 if (status
!= GSS_S_COMPLETE
)
1131 *acceptor_name
= (gss_name_t
)name2
;
1133 if (lifetime_rec
) /* user may pass a null pointer */
1134 *lifetime_rec
= GSS_C_INDEFINITE
;
1136 *mech_type
= (gss_OID
)gss_mech_dummy
;
1138 *ret_flags
= dummy_flags
;
1140 *open
= ctx
->established
;
1142 dprintf("Leaving inquire_context\n");
1143 return (GSS_S_COMPLETE
);
1148 dummy_gss_internal_release_oid(ct
, minor_status
, oid
)
1150 OM_uint32
*minor_status
;
1153 dprintf("Entering internal_release_oid\n");
1155 /* Similar to krb5_gss_internal_release_oid */
1157 if (*oid
!= gss_mech_dummy
)
1158 return (GSS_S_CONTINUE_NEEDED
); /* We don't know this oid */
1161 *oid
= GSS_C_NO_OID
;
1163 dprintf("Leaving internal_release_oid\n");
1164 return (GSS_S_COMPLETE
);
1169 dummy_gss_wrap_size_limit(ct
, minor_status
, context_handle
, conf_req_flag
,
1170 qop_req
, req_output_size
, max_input_size
)
1172 OM_uint32
*minor_status
;
1173 gss_ctx_id_t context_handle
;
1176 OM_uint32 req_output_size
;
1177 OM_uint32
*max_input_size
;
1179 dprintf("Entering wrap_size_limit\n");
1180 *max_input_size
= req_output_size
;
1181 dprintf("Leaving wrap_size_limit\n");
1182 return (GSS_S_COMPLETE
);
1187 dummy_pname_to_uid(ct
, minor_status
, name
, uidOut
)
1189 OM_uint32
*minor_status
;
1190 const gss_name_t name
;
1193 dprintf("Entering pname_to_uid\n");
1196 dprintf("Leaving pname_to_uid\n");
1197 return (GSS_S_COMPLETE
);
1200 static dummy_token_t
1201 make_dummy_token(char *name
)
1203 dummy_token_t token
;
1205 token
= (dummy_token_t
)malloc(strlen(name
)+1);
1206 strcpy(token
, name
);
1211 free_dummy_token(dummy_token_t
*token
)
1217 static gss_buffer_desc
1218 make_dummy_token_buffer(char *name
)
1220 gss_buffer_desc buffer
;
1224 buffer
.value
= NULL
;
1226 buffer
.length
= strlen(name
)+1;
1227 buffer
.value
= make_dummy_token(name
);
1232 static gss_buffer_desc
1233 make_dummy_token_msg(void *data
, int dataLen
)
1235 gss_buffer_desc buffer
;
1242 buffer
.value
= NULL
;
1246 tlen
= g_token_size((gss_OID
)gss_mech_dummy
, dataLen
);
1247 t
= (unsigned char *) malloc(tlen
);
1250 g_make_token_header((gss_OID
)gss_mech_dummy
, dataLen
, &ptr
, 0);
1251 memcpy(ptr
, data
, dataLen
);
1253 buffer
.length
= tlen
;
1254 buffer
.value
= (void *) t
;
1259 der_length_size(length
)
1262 if (length
< (1<<7))
1264 else if (length
< (1<<8))
1266 else if (length
< (1<<16))
1268 else if (length
< (1<<24))
1275 der_write_length(buf
, length
)
1276 unsigned char **buf
;
1279 if (length
< (1<<7)) {
1280 *(*buf
)++ = (unsigned char) length
;
1282 *(*buf
)++ = (unsigned char) (der_length_size(length
)+127);
1283 if (length
>= (1<<24))
1284 *(*buf
)++ = (unsigned char) (length
>>24);
1285 if (length
>= (1<<16))
1286 *(*buf
)++ = (unsigned char) ((length
>>16)&0xff);
1287 if (length
>= (1<<8))
1288 *(*buf
)++ = (unsigned char) ((length
>>8)&0xff);
1289 *(*buf
)++ = (unsigned char) (length
&0xff);
1294 der_read_length(buf
, bufsize
)
1295 unsigned char **buf
;
1307 if ((sf
&= 0x7f) > ((*bufsize
)-1))
1310 if (sf
> DUMMY_SIZE_OF_INT
)
1314 ret
= (ret
<<8) + (*(*buf
)++);
1325 g_token_size(mech
, body_size
)
1327 unsigned int body_size
;
1329 /* set body_size to sequence contents size */
1330 body_size
+= 4 + (int)mech
->length
; /* NEED overflow check */
1331 return (1 + der_length_size(body_size
) + body_size
);
1335 g_make_token_header(mech
, body_size
, buf
, tok_type
)
1338 unsigned char **buf
;
1342 der_write_length(buf
, 4 + mech
->length
+ body_size
);
1344 *(*buf
)++ = (unsigned char) mech
->length
;
1345 TWRITE_STR(*buf
, mech
->elements
, ((int)mech
->length
));
1346 *(*buf
)++ = (unsigned char) ((tok_type
>>8)&0xff);
1347 *(*buf
)++ = (unsigned char) (tok_type
&0xff);
1351 g_verify_token_header(mech
, body_size
, buf_in
, tok_type
, toksize
)
1354 unsigned char **buf_in
;
1358 unsigned char *buf
= *buf_in
;
1363 if ((toksize
-= 1) < 0)
1364 return (G_BAD_TOK_HEADER
);
1366 return (G_BAD_TOK_HEADER
);
1368 if ((seqsize
= der_read_length(&buf
, &toksize
)) < 0)
1369 return (G_BAD_TOK_HEADER
);
1371 if (seqsize
!= toksize
)
1372 return (G_BAD_TOK_HEADER
);
1374 if ((toksize
-= 1) < 0)
1375 return (G_BAD_TOK_HEADER
);
1377 return (G_BAD_TOK_HEADER
);
1379 if ((toksize
-= 1) < 0)
1380 return (G_BAD_TOK_HEADER
);
1381 toid
.length
= *buf
++;
1383 if ((toksize
-= toid
.length
) < 0)
1384 return (G_BAD_TOK_HEADER
);
1385 toid
.elements
= buf
;
1388 if (!g_OID_equal(&toid
, mech
))
1392 * G_WRONG_MECH is not returned immediately because it's more important
1393 * to return G_BAD_TOK_HEADER if the token header is in fact bad
1396 if ((toksize
-= 2) < 0)
1397 return (G_BAD_TOK_HEADER
);
1399 if ((*buf
++ != ((tok_type
>>8)&0xff)) ||
1400 (*buf
++ != (tok_type
&0xff)))
1401 return (G_BAD_TOK_HEADER
);
1405 *body_size
= toksize
;