Merge illumos-gate
[unleashed/lotheac.git] / usr / src / lib / gss_mechs / mech_dummy / mech / dmech.c
blob0e94f575f6c3521bc865b1f9dfa71aab7ee614d7
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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 \
34 dummy_867227349
35 #define dummy_gss_acquire_cred \
36 dummy_352458907
37 #define dummy_gss_add_cred \
38 dummy_911432290
39 #define dummy_gss_compare_name \
40 dummy_396663848
41 #define dummy_gss_context_time \
42 dummy_955669998
43 #define dummy_gss_delete_sec_context \
44 dummy_440868788
45 #define dummy_gss_display_name \
46 dummy_999874939
47 #define dummy_gss_display_status \
48 dummy_485073729
49 #define dummy_gss_export_sec_context \
50 dummy_1044079879
51 #define dummy_gss_import_name \
52 dummy_529311438
53 #define dummy_gss_import_sec_context \
54 dummy_14542996
55 #define dummy_gss_indicate_mechs \
56 dummy_573516378
57 #define dummy_gss_init_sec_context \
58 dummy_58780705
59 #define dummy_gss_inquire_context \
60 dummy_617721319
61 #define dummy_gss_inquire_cred \
62 dummy_102985645
63 #define dummy_gss_inquire_cred_by_mech \
64 dummy_661926260
65 #define dummy_gss_inquire_names_for_mech \
66 dummy_147190586
67 #define dummy_gss_internal_release_oid \
68 dummy_706163968
69 #define dummy_gss_process_context_token \
70 dummy_191395526
71 #define dummy_gss_release_cred \
72 dummy_750368909
73 #define dummy_gss_release_name \
74 dummy_235600467
75 #define dummy_gss_seal \
76 dummy_794573849
77 #define dummy_gss_sign \
78 dummy_279838176
79 #define dummy_gss_unseal \
80 dummy_838778790
81 #define dummy_gss_verify \
82 dummy_324010348
83 #define dummy_gss_wrap_size_limit \
84 dummy_882983731
85 #define dummy_pname_to_uid \
86 dummy_345475423
88 #include <stdio.h>
89 #include <stdlib.h>
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,
108 int toksize);
111 /* private global variables */
112 static char dummy_srcname[] = "dummy source";
113 static OM_uint32 dummy_flags;
114 static int token_nums;
117 * The Mech OID:
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"},
123 NULL,
124 dummy_gss_acquire_cred,
125 dummy_gss_release_cred,
126 dummy_gss_init_sec_context,
127 dummy_gss_accept_sec_context,
128 dummy_gss_unseal,
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,
139 dummy_gss_add_cred,
140 dummy_gss_seal,
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,
148 dummy_pname_to_uid,
149 NULL, /* __gss_userok */
150 NULL, /* _export name */
151 dummy_gss_sign,
152 dummy_gss_verify,
153 NULL, /* _store_cred */
156 gss_mechanism
157 gss_mech_initialize(oid)
158 const gss_OID oid;
160 FILE *fp;
162 dprintf("Entering gss_mech_initialize\n");
164 if (oid == NULL ||
165 !g_OID_equal(oid, &dummy_mechanism.mech_type)) {
166 fprintf(stderr, "invalid dummy mechanism oid.\n");
167 return (NULL);
170 fp = fopen("/etc/dummy_mech_token.conf", "rF");
171 if (fp == NULL) {
172 fprintf(stderr, "dummy_mech.conf is not found.\n");
173 fprintf(stderr, "Setting number tokens exchanged to 1\n");
174 token_nums = 1;
175 } else {
176 fscanf(fp, "%d", &token_nums);
177 fclose(fp);
178 dprintf("dummy_mech.conf is found.\n");
179 dprintf1("Setting number tokens exchanged to %d\n", token_nums);
182 if (token_nums == 1)
183 dummy_flags = GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
184 else
185 dummy_flags = GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG
186 | GSS_C_MUTUAL_FLAG;
188 dprintf("Leaving gss_mech_initialize\n");
189 return (&dummy_mechanism);
192 /*ARGSUSED*/
193 OM_uint32
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)
197 void *ctx;
198 OM_uint32 *minor_status;
199 gss_name_t desired_name;
200 OM_uint32 time_req;
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;
205 OM_uint32 *time_rec;
207 dprintf("Entering dummy_gss_acquire_cred\n");
209 if (actual_mechs)
210 *actual_mechs = NULL;
211 if (time_rec)
212 *time_rec = 0;
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;
218 if (actual_mechs) {
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);
229 /*ARGSUSED*/
230 OM_uint32
231 dummy_gss_release_cred(ctx, minor_status, cred_handle)
232 void *ctx;
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));
239 *cred_handle = NULL;
241 dprintf("Leaving dummy_gss_release_cred\n");
242 return (GSS_S_COMPLETE);
245 /*ARGSUSED*/
246 OM_uint32
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,
251 ret_flags, time_rec)
252 void *ct;
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;
257 gss_OID mech_type;
258 OM_uint32 req_flags;
259 OM_uint32 time_req;
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;
265 OM_uint32 *time_rec;
267 dummy_gss_ctx_id_t ctx;
268 char token_string[64];
269 OM_uint32 ret;
270 OM_uint32 aret;
271 int send_token = 0;
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;
295 } else {
296 ret = GSS_S_COMPLETE;
298 send_token = 1;
299 } else {
300 unsigned char *ptr;
301 int bodysize;
302 int err;
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)) {
316 *minor_status = err;
317 ctx->last_stat = GSS_S_DEFECTIVE_TOKEN;
318 return (GSS_S_DEFECTIVE_TOKEN);
321 if (sscanf((char *)ptr, "%d", &aret) < 1) {
322 *minor_status = 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
336 * a problem.
338 ctx->last_stat = GSS_S_FAILURE;
339 return (GSS_S_FAILURE);
341 ret = GSS_S_CONTINUE_NEEDED;
342 send_token = 1;
343 } else {
344 ret = GSS_S_COMPLETE;
345 send_token = 0;
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);
360 } else {
361 *output_token = make_dummy_token_msg(NULL, 0);
364 if (ret == GSS_S_COMPLETE)
365 ctx->established = 1;
367 ctx->last_stat = ret;
368 return (ret);
371 /*ARGSUSED*/
372 OM_uint32
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)
378 void *ct;
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;
385 gss_OID *mech_type;
386 gss_buffer_t output_token;
387 OM_uint32 *ret_flags;
388 OM_uint32 *time_rec;
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;
394 OM_uint32 status;
395 gss_name_t temp;
396 unsigned char *ptr;
397 int bodysize;
398 int err;
399 OM_uint32 iret;
400 int return_token = 0;
402 dprintf("Entering accept_sec_context\n");
404 if (src_name)
405 *src_name = (gss_name_t)NULL;
406 output_token->length = 0;
407 output_token->value = NULL;
408 if (mech_type)
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,
417 &ptr, 0,
418 input_token->length)) {
419 *minor_status = err;
420 return (GSS_S_DEFECTIVE_TOKEN);
423 if (sscanf((char *)ptr, "%d", &iret) < 1) {
424 *minor_status = 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;
433 } else {
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;
441 if (mech_type)
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)
450 return_token = 1;
451 else
452 return_token = 0;
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;
463 else
464 status = GSS_S_COMPLETE;
466 } else
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;
478 return (status);
480 *src_name = temp;
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);
492 } else {
493 *output_token = make_dummy_token_msg(NULL, 0);
496 if (ctx->token_number > 0)
497 ctx->token_number--;
499 return (status);
503 /*ARGSUSED*/
504 OM_uint32
505 dummy_gss_process_context_token(ct, minor_status, context_handle, token_buffer)
506 void *ct;
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);
515 /*ARGSUSED*/
516 OM_uint32
517 dummy_gss_delete_sec_context(ct, minor_status, context_handle, output_token)
518 void *ct;
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 */
528 if (output_token) {
529 output_token->length = 0;
530 output_token->value = NULL;
533 if (*context_handle == GSS_C_NO_CONTEXT) {
534 *minor_status = 0;
535 return (GSS_S_COMPLETE);
538 ctx = (dummy_gss_ctx_id_t)*context_handle;
539 free(ctx);
540 *context_handle = GSS_C_NO_CONTEXT;
542 dprintf("Leaving delete_sec_context\n");
543 return (GSS_S_COMPLETE);
547 /*ARGSUSED*/
548 OM_uint32
549 dummy_gss_context_time(ct, minor_status, context_handle, time_rec)
550 void *ct;
551 OM_uint32 *minor_status;
552 gss_ctx_id_t context_handle;
553 OM_uint32 *time_rec;
555 dprintf("In context_time\n");
556 if (time_rec) /* user may pass a null pointer */
557 return (GSS_S_FAILURE);
558 else
559 *time_rec = GSS_C_INDEFINITE;
560 return (GSS_S_COMPLETE);
563 /*ARGSUSED*/
564 OM_uint32
565 dummy_gss_sign(ctx, minor_status, context_handle,
566 qop_req, message_buffer, message_token)
567 void *ctx;
568 OM_uint32 *minor_status;
569 gss_ctx_id_t context_handle;
570 int qop_req;
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);
592 /*ARGSUSED*/
593 OM_uint32
594 dummy_gss_verify(ctx, minor_status, context_handle,
595 message_buffer, token_buffer, qop_state)
596 void *ctx;
597 OM_uint32 *minor_status;
598 gss_ctx_id_t context_handle;
599 gss_buffer_t message_buffer;
600 gss_buffer_t token_buffer;
601 int *qop_state;
603 unsigned char *ptr;
604 int bodysize;
605 int err;
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,
619 &ptr, 0,
620 token_buffer->length)) {
621 *minor_status = err;
622 return (GSS_S_DEFECTIVE_TOKEN);
625 if (qop_state)
626 *qop_state = GSS_C_QOP_DEFAULT;
628 dprintf("Leaving gss_verify\n");
629 return (GSS_S_COMPLETE);
632 /*ARGSUSED*/
633 OM_uint32
634 dummy_gss_seal(ctx, minor_status, context_handle, conf_req_flag,
635 qop_req, input_message_buffer, conf_state,
636 output_message_buffer)
637 void *ctx;
638 OM_uint32 *minor_status;
639 gss_ctx_id_t context_handle;
640 int conf_req_flag;
641 int qop_req;
642 gss_buffer_t input_message_buffer;
643 int *conf_state;
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);
661 if (conf_state)
662 *conf_state = 1;
664 *output_message_buffer = output;
666 dprintf("Leaving gss_seal\n");
667 return (GSS_S_COMPLETE);
673 /*ARGSUSED*/
674 OM_uint32
675 dummy_gss_unseal(ctx, minor_status, context_handle,
676 input_message_buffer, output_message_buffer,
677 conf_state, qop_state)
678 void *ctx;
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;
683 int *conf_state;
684 int *qop_state;
686 gss_buffer_desc output;
687 unsigned char *ptr;
688 int bodysize;
689 int err;
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,
702 &ptr, 0,
703 input_message_buffer->length)) {
704 *minor_status = err;
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;
712 if (qop_state)
713 *qop_state = GSS_C_QOP_DEFAULT;
714 if (conf_state)
715 *conf_state = 1;
717 dprintf("Leaving gss_unseal\n");
718 return (GSS_S_COMPLETE);
721 /*ARGSUSED*/
722 OM_uint32
723 dummy_gss_display_status(ctx, minor_status, status_value, status_type,
724 mech_type, message_context, status_string)
725 void *ctx;
726 OM_uint32 *minor_status;
727 OM_uint32 status_value;
728 int status_type;
729 gss_OID mech_type;
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);
742 /*ARGSUSED*/
743 OM_uint32
744 dummy_gss_indicate_mechs(ctx, minor_status, mech_set)
745 void *ctx;
746 OM_uint32 *minor_status;
747 gss_OID_set *mech_set;
749 dprintf("Entering indicate_mechs\n");
751 *minor_status = 0;
752 if (mech_set) {
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);
763 /*ARGSUSED*/
764 OM_uint32
765 dummy_gss_compare_name(ctx, minor_status, name1, name2, name_equal)
766 void *ctx;
767 OM_uint32 *minor_status;
768 gss_name_t name1;
769 gss_name_t name2;
770 int *name_equal;
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))
781 *name_equal = 1;
782 else
783 *name_equal = 0;
785 dprintf("Leaving compare_name\n");
786 return (GSS_S_COMPLETE);
789 /*ARGSUSED*/
790 OM_uint32
791 dummy_gss_display_name(ctx, minor_status, input_name, output_name_buffer,
792 output_name_type)
793 void *ctx;
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");
827 return (status);
830 dprintf("Leaving display_name\n");
831 return (GSS_S_BAD_NAMETYPE);
834 /*ARGSUSED*/
835 OM_uint32
836 dummy_gss_import_name(ctx, minor_status, input_name_buffer,
837 input_name_type, output_name)
838 void *ctx;
839 OM_uint32 *minor_status;
840 gss_buffer_t input_name_buffer;
841 gss_OID input_name_type;
842 gss_name_t *output_name;
844 OM_uint32 status;
846 dprintf("Entering import_name\n");
848 *output_name = NULL;
849 *minor_status = 0;
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");
873 return (status);
875 dprintf("Leaving import_name\n");
876 return (GSS_S_BAD_NAMETYPE);
879 /*ARGSUSED*/
880 OM_uint32
881 dummy_gss_release_name(ctx, minor_status, input_name)
882 void *ctx;
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));
891 free(name->buffer);
892 free(name);
893 dprintf("Leaving release_name\n");
894 return (GSS_S_COMPLETE);
897 /*ARGSUSED*/
898 OM_uint32
899 dummy_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
900 cred_usage, mechanisms)
901 void *ctx;
902 OM_uint32 *minor_status;
903 gss_cred_id_t cred_handle;
904 gss_name_t *name;
905 OM_uint32 *lifetime_ret;
906 gss_cred_usage_t *cred_usage;
907 gss_OID_set *mechanisms;
909 dprintf("Entering inquire_cred\n");
910 if (name)
911 *name = (gss_name_t)make_dummy_token
912 ("dummy gss credential");
913 if (lifetime_ret)
914 *lifetime_ret = GSS_C_INDEFINITE;
915 if (cred_usage)
916 *cred_usage = GSS_C_BOTH;
917 if (mechanisms) {
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);
927 /*ARGSUSED*/
928 OM_uint32
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)
934 void *ctx;
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);
952 *minor_status = 0;
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 */
958 /* this error */
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). */
969 /*ARGSUSED*/
970 OM_uint32
971 dummy_gss_export_sec_context(ct, minor_status, context_handle,
972 interprocess_token)
973 void *ct;
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);
990 /*ARGSUSED*/
991 OM_uint32
992 dummy_gss_import_sec_context(ct, minor_status, interprocess_token,
993 context_handle)
994 void *ct;
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);
1014 /*ARGSUSED*/
1015 OM_uint32
1016 dummy_gss_inquire_cred_by_mech(ctx, minor_status, cred_handle,
1017 mech_type, name, initiator_lifetime,
1018 acceptor_lifetime, cred_usage)
1019 void *ctx;
1020 OM_uint32 *minor_status;
1021 gss_cred_id_t cred_handle;
1022 gss_OID mech_type;
1023 gss_name_t *name;
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");
1029 if (name)
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;
1035 if (cred_usage)
1036 *cred_usage = GSS_C_BOTH;
1038 dprintf("Leaving inquire_cred_by_mech\n");
1039 return (GSS_S_COMPLETE);
1042 /*ARGSUSED*/
1043 OM_uint32
1044 dummy_gss_inquire_names_for_mech(ctx, minor_status, mechanism, name_types)
1045 void *ctx;
1046 OM_uint32 *minor_status;
1047 gss_OID mechanism;
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)) {
1058 *minor_status = 0;
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");
1083 return (major);
1086 /*ARGSUSED*/
1087 OM_uint32
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)
1091 void *ct;
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;
1097 gss_OID *mech_type;
1098 OM_uint32 *ret_flags;
1099 int *locally_initiated;
1100 int *open;
1102 dummy_gss_ctx_id_t ctx;
1103 dummy_name_t name1, name2;
1104 OM_uint32 status;
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)
1117 return (status);
1118 if (initiator_name)
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)
1129 return (status);
1130 if (acceptor_name)
1131 *acceptor_name = (gss_name_t)name2;
1133 if (lifetime_rec) /* user may pass a null pointer */
1134 *lifetime_rec = GSS_C_INDEFINITE;
1135 if (mech_type)
1136 *mech_type = (gss_OID)gss_mech_dummy;
1137 if (ret_flags)
1138 *ret_flags = dummy_flags;
1139 if (open)
1140 *open = ctx->established;
1142 dprintf("Leaving inquire_context\n");
1143 return (GSS_S_COMPLETE);
1146 /*ARGSUSED*/
1147 OM_uint32
1148 dummy_gss_internal_release_oid(ct, minor_status, oid)
1149 void *ct;
1150 OM_uint32 *minor_status;
1151 gss_OID *oid;
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 */
1160 *minor_status = 0;
1161 *oid = GSS_C_NO_OID;
1163 dprintf("Leaving internal_release_oid\n");
1164 return (GSS_S_COMPLETE);
1167 /*ARGSUSED*/
1168 OM_uint32
1169 dummy_gss_wrap_size_limit(ct, minor_status, context_handle, conf_req_flag,
1170 qop_req, req_output_size, max_input_size)
1171 void *ct;
1172 OM_uint32 *minor_status;
1173 gss_ctx_id_t context_handle;
1174 int conf_req_flag;
1175 gss_qop_t qop_req;
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);
1185 /* ARGSUSED */
1186 OM_uint32
1187 dummy_pname_to_uid(ct, minor_status, name, uidOut)
1188 void *ct;
1189 OM_uint32 *minor_status;
1190 const gss_name_t name;
1191 uid_t *uidOut;
1193 dprintf("Entering pname_to_uid\n");
1194 *minor_status = 0;
1195 *uidOut = 60001;
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);
1207 return (token);
1210 static void
1211 free_dummy_token(dummy_token_t *token)
1213 free(*token);
1214 *token = NULL;
1217 static gss_buffer_desc
1218 make_dummy_token_buffer(char *name)
1220 gss_buffer_desc buffer;
1222 if (name == NULL) {
1223 buffer.length = 0;
1224 buffer.value = NULL;
1225 } else {
1226 buffer.length = strlen(name)+1;
1227 buffer.value = make_dummy_token(name);
1229 return (buffer);
1232 static gss_buffer_desc
1233 make_dummy_token_msg(void *data, int dataLen)
1235 gss_buffer_desc buffer;
1236 int tlen;
1237 unsigned char *t;
1238 unsigned char *ptr;
1240 if (data == NULL) {
1241 buffer.length = 0;
1242 buffer.value = NULL;
1243 return (buffer);
1246 tlen = g_token_size((gss_OID)gss_mech_dummy, dataLen);
1247 t = (unsigned char *) malloc(tlen);
1248 ptr = t;
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;
1255 return (buffer);
1258 static int
1259 der_length_size(length)
1260 int length;
1262 if (length < (1<<7))
1263 return (1);
1264 else if (length < (1<<8))
1265 return (2);
1266 else if (length < (1<<16))
1267 return (3);
1268 else if (length < (1<<24))
1269 return (4);
1270 else
1271 return (5);
1274 static void
1275 der_write_length(buf, length)
1276 unsigned char **buf;
1277 int length;
1279 if (length < (1<<7)) {
1280 *(*buf)++ = (unsigned char) length;
1281 } else {
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);
1293 static int
1294 der_read_length(buf, bufsize)
1295 unsigned char **buf;
1296 int *bufsize;
1298 unsigned char sf;
1299 int ret;
1301 if (*bufsize < 1)
1302 return (-1);
1304 sf = *(*buf)++;
1305 (*bufsize)--;
1306 if (sf & 0x80) {
1307 if ((sf &= 0x7f) > ((*bufsize)-1))
1308 return (-1);
1310 if (sf > DUMMY_SIZE_OF_INT)
1311 return (-1);
1312 ret = 0;
1313 for (; sf; sf--) {
1314 ret = (ret<<8) + (*(*buf)++);
1315 (*bufsize)--;
1317 } else {
1318 ret = sf;
1321 return (ret);
1324 static int
1325 g_token_size(mech, body_size)
1326 gss_OID mech;
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);
1334 static void
1335 g_make_token_header(mech, body_size, buf, tok_type)
1336 gss_OID mech;
1337 int body_size;
1338 unsigned char **buf;
1339 int tok_type;
1341 *(*buf)++ = 0x60;
1342 der_write_length(buf, 4 + mech->length + body_size);
1343 *(*buf)++ = 0x06;
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);
1350 static int
1351 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize)
1352 gss_OID mech;
1353 int *body_size;
1354 unsigned char **buf_in;
1355 int tok_type;
1356 int toksize;
1358 unsigned char *buf = *buf_in;
1359 int seqsize;
1360 gss_OID_desc toid;
1361 int ret = 0;
1363 if ((toksize -= 1) < 0)
1364 return (G_BAD_TOK_HEADER);
1365 if (*buf++ != 0x60)
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);
1376 if (*buf++ != 0x06)
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;
1386 buf += toid.length;
1388 if (!g_OID_equal(&toid, mech))
1389 ret = G_WRONG_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);
1403 if (!ret) {
1404 *buf_in = buf;
1405 *body_size = toksize;
1408 return (ret);