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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
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.
26 *
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.
31 *
32 */
33 #ifndef lint
34 #define dummy_gss_accept_sec_context \
35 dummy_867227349
36 #define dummy_gss_acquire_cred \
37 dummy_352458907
38 #define dummy_gss_add_cred \
39 dummy_911432290
40 #define dummy_gss_compare_name \
41 dummy_396663848
42 #define dummy_gss_context_time \
43 dummy_955669998
44 #define dummy_gss_delete_sec_context \
45 dummy_440868788
46 #define dummy_gss_display_name \
47 dummy_999874939
48 #define dummy_gss_display_status \
49 dummy_485073729
50 #define dummy_gss_export_sec_context \
51 dummy_1044079879
52 #define dummy_gss_import_name \
53 dummy_529311438
54 #define dummy_gss_import_sec_context \
55 dummy_14542996
56 #define dummy_gss_indicate_mechs \
57 dummy_573516378
58 #define dummy_gss_init_sec_context \
59 dummy_58780705
60 #define dummy_gss_inquire_context \
61 dummy_617721319
62 #define dummy_gss_inquire_cred \
63 dummy_102985645
64 #define dummy_gss_inquire_cred_by_mech \
65 dummy_661926260
66 #define dummy_gss_inquire_names_for_mech \
67 dummy_147190586
68 #define dummy_gss_internal_release_oid \
69 dummy_706163968
70 #define dummy_gss_process_context_token \
71 dummy_191395526
72 #define dummy_gss_release_cred \
73 dummy_750368909
74 #define dummy_gss_release_name \
75 dummy_235600467
76 #define dummy_gss_seal \
77 dummy_794573849
78 #define dummy_gss_sign \
79 dummy_279838176
80 #define dummy_gss_unseal \
81 dummy_838778790
82 #define dummy_gss_verify \
83 dummy_324010348
84 #define dummy_gss_wrap_size_limit \
85 dummy_882983731
86 #define dummy_pname_to_uid \
87 dummy_345475423
88 #endif
89
90 #include <stdio.h>
91 #include <stdlib.h>
92 #include <gssapiP_dummy.h>
93 #include <mechglueP.h>
94 #include <gssapi_err_generic.h>
95
96 #define dummy_context_name_len 19
97 /* private routines for dummy_mechanism */
98 static dummy_token_t make_dummy_token(char *name);
99 static void free_dummy_token(dummy_token_t *token);
100 static gss_buffer_desc make_dummy_token_buffer(char *name);
101 static gss_buffer_desc make_dummy_token_msg(void *data, int datalen);
102 static int der_length_size(int length);
103 static void der_write_length(unsigned char ** buf, int length);
104 static int der_read_length(unsigned char **buf, int *bufsize);
105 static int g_token_size(gss_OID mech, unsigned int body_size);
106 static void g_make_token_header(gss_OID mech, int body_size,
107 unsigned char **buf, int tok_type);
108 static int g_verify_token_header(gss_OID mech, int *body_size,
109 unsigned char **buf_in, int tok_type,
110 int toksize);
111
112
113 /* private global variables */
114 static char dummy_srcname[] = "dummy source";
115 static OM_uint32 dummy_flags;
116 static int token_nums;
117
118 /*
119 * The Mech OID:
120 * { iso(1) org(3) internet(6) dod(1) private(4) enterprises(1) sun(42)
121 * products(2) gssapi(26) mechtypes(1) dummy(2) }
122 */
123 static struct gss_config dummy_mechanism =
124 {{10, "\053\006\001\004\001\052\002\032\001\002"},
125 NULL,
126 dummy_gss_acquire_cred,
127 dummy_gss_release_cred,
128 dummy_gss_init_sec_context,
129 dummy_gss_accept_sec_context,
130 dummy_gss_unseal,
131 dummy_gss_process_context_token,
132 dummy_gss_delete_sec_context,
133 dummy_gss_context_time,
134 dummy_gss_display_status,
135 dummy_gss_indicate_mechs,
136 dummy_gss_compare_name,
137 dummy_gss_display_name,
138 dummy_gss_import_name,
139 dummy_gss_release_name,
140 dummy_gss_inquire_cred,
141 dummy_gss_add_cred,
142 dummy_gss_seal,
143 dummy_gss_export_sec_context,
144 dummy_gss_import_sec_context,
145 dummy_gss_inquire_cred_by_mech,
146 dummy_gss_inquire_names_for_mech,
147 dummy_gss_inquire_context,
148 dummy_gss_internal_release_oid,
149 dummy_gss_wrap_size_limit,
150 dummy_pname_to_uid,
151 NULL, /* __gss_userok */
152 NULL, /* _export name */
153 dummy_gss_sign,
154 dummy_gss_verify,
155 NULL, /* _store_cred */
156 };
157
158 gss_mechanism
gss_mech_initialize(oid)159 gss_mech_initialize(oid)
160 const gss_OID oid;
161 {
162 FILE *fp;
163
164 dprintf("Entering gss_mech_initialize\n");
165
166 if (oid == NULL ||
167 !g_OID_equal(oid, &dummy_mechanism.mech_type)) {
168 fprintf(stderr, "invalid dummy mechanism oid.\n");
169 return (NULL);
170 }
171
172 fp = fopen("/etc/dummy_mech_token.conf", "rF");
173 if (fp == NULL) {
174 fprintf(stderr, "dummy_mech.conf is not found.\n");
175 fprintf(stderr, "Setting number tokens exchanged to 1\n");
176 token_nums = 1;
177 } else {
178 fscanf(fp, "%d", &token_nums);
179 fclose(fp);
180 dprintf("dummy_mech.conf is found.\n");
181 dprintf1("Setting number tokens exchanged to %d\n", token_nums);
182 }
183
184 if (token_nums == 1)
185 dummy_flags = GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
186 else
187 dummy_flags = GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG
188 | GSS_C_MUTUAL_FLAG;
189
190 dprintf("Leaving gss_mech_initialize\n");
191 return (&dummy_mechanism);
192 }
193
194 /*ARGSUSED*/
195 OM_uint32
dummy_gss_acquire_cred(ctx,minor_status,desired_name,time_req,desired_mechs,cred_usage,output_cred_handle,actual_mechs,time_rec)196 dummy_gss_acquire_cred(ctx, minor_status, desired_name, time_req, desired_mechs,
197 cred_usage, output_cred_handle,
198 actual_mechs, time_rec)
199 void *ctx;
200 OM_uint32 *minor_status;
201 gss_name_t desired_name;
202 OM_uint32 time_req;
203 gss_OID_set desired_mechs;
204 gss_cred_usage_t cred_usage;
205 gss_cred_id_t *output_cred_handle;
206 gss_OID_set *actual_mechs;
207 OM_uint32 *time_rec;
208 {
209 dprintf("Entering dummy_gss_acquire_cred\n");
210
211 if (actual_mechs)
212 *actual_mechs = NULL;
213 if (time_rec)
214 *time_rec = 0;
215
216 *output_cred_handle = (gss_cred_id_t)
217 make_dummy_token("dummy_gss_acquire_cred");
218 if (time_rec) /* user may pass a null pointer */
219 *time_rec = GSS_C_INDEFINITE;
220 if (actual_mechs) {
221 if (gss_copy_oid_set(minor_status, gss_mech_set_dummy,
222 actual_mechs) == GSS_S_FAILURE) {
223 return (GSS_S_FAILURE);
224 }
225 }
226
227 dprintf("Leaving dummy_gss_acquire_cred\n");
228 return (GSS_S_COMPLETE);
229 }
230
231 /*ARGSUSED*/
232 OM_uint32
dummy_gss_release_cred(ctx,minor_status,cred_handle)233 dummy_gss_release_cred(ctx, minor_status, cred_handle)
234 void *ctx;
235 OM_uint32 *minor_status;
236 gss_cred_id_t *cred_handle;
237 {
238 dprintf("Entering dummy_gss_release_cred\n");
239
240 free_dummy_token((dummy_token_t *)(cred_handle));
241 *cred_handle = NULL;
242
243 dprintf("Leaving dummy_gss_release_cred\n");
244 return (GSS_S_COMPLETE);
245 }
246
247 /*ARGSUSED*/
248 OM_uint32
dummy_gss_init_sec_context(ct,minor_status,claimant_cred_handle,context_handle,target_name,mech_type,req_flags,time_req,input_chan_bindings,input_token,actual_mech_type,output_token,ret_flags,time_rec)249 dummy_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
250 context_handle, target_name, mech_type,
251 req_flags, time_req, input_chan_bindings,
252 input_token, actual_mech_type, output_token,
253 ret_flags, time_rec)
254 void *ct;
255 OM_uint32 *minor_status;
256 gss_cred_id_t claimant_cred_handle;
257 gss_ctx_id_t *context_handle;
258 gss_name_t target_name;
259 gss_OID mech_type;
260 OM_uint32 req_flags;
261 OM_uint32 time_req;
262 gss_channel_bindings_t input_chan_bindings;
263 gss_buffer_t input_token;
264 gss_OID *actual_mech_type;
265 gss_buffer_t output_token;
266 OM_uint32 *ret_flags;
267 OM_uint32 *time_rec;
268 {
269 dummy_gss_ctx_id_t ctx;
270 char token_string[64];
271 OM_uint32 ret;
272 OM_uint32 aret;
273 int send_token = 0;
274
275 dprintf("Entering init_sec_context\n");
276
277 output_token->length = 0;
278 output_token->value = NULL;
279 if (actual_mech_type)
280 *actual_mech_type = NULL;
281
282 if (*context_handle == GSS_C_NO_CONTEXT) {
283
284 if (input_token != NULL && input_token->value != NULL)
285 return (GSS_S_FAILURE);
286
287 ctx = (dummy_gss_ctx_id_t)malloc(sizeof (dummy_gss_ctx_id_rec));
288 ctx->established = 0;
289 ctx->last_stat = 0xffffffff;
290 *context_handle = (gss_ctx_id_t)ctx;
291 /*
292 * Initiator interpretation of config file. If 2 or more
293 * the client returns CONTINUE_NNED on the first call.
294 */
295 if (token_nums >= 2) {
296 ret = GSS_S_CONTINUE_NEEDED;
297 } else {
298 ret = GSS_S_COMPLETE;
299 }
300 send_token = 1;
301 } else {
302 unsigned char *ptr;
303 int bodysize;
304 int err;
305
306 if (input_token == NULL || input_token->value == NULL) {
307 ctx->last_stat = GSS_S_FAILURE;
308 return (GSS_S_FAILURE);
309 }
310
311 ctx = (dummy_gss_ctx_id_t)(*context_handle);
312
313
314 ptr = (unsigned char *) input_token->value;
315 if (err = g_verify_token_header((gss_OID)gss_mech_dummy,
316 &bodysize, &ptr, 0, input_token->length)) {
317
318 *minor_status = err;
319 ctx->last_stat = GSS_S_DEFECTIVE_TOKEN;
320 return (GSS_S_DEFECTIVE_TOKEN);
321 }
322
323 if (sscanf((char *)ptr, "%d", &aret) < 1) {
324 *minor_status = 1;
325 ctx->last_stat = GSS_S_DEFECTIVE_TOKEN;
326 return (GSS_S_DEFECTIVE_TOKEN);
327 }
328
329 if (aret == GSS_S_CONTINUE_NEEDED) {
330 if (ctx->last_stat == GSS_S_COMPLETE) {
331 /*
332 * RFC 2078, page 36, under GSS_S_COMPLETE
333 * says that acceptor (target) has sufficient
334 * information to perform per-message
335 * processing. So if initiator previously
336 * returned GSS_S_COMPLETE, and acceptor
337 * says it needs more, then we have
338 * a problem.
339 */
340 ctx->last_stat = GSS_S_FAILURE;
341 return (GSS_S_FAILURE);
342 }
343 ret = GSS_S_CONTINUE_NEEDED;
344 send_token = 1;
345 } else {
346 ret = GSS_S_COMPLETE;
347 send_token = 0;
348 }
349 }
350 if (ret_flags) /* user may pass a null pointer */
351 *ret_flags = dummy_flags;
352 if (time_rec) /* user may pass a null pointer */
353 *time_rec = GSS_C_INDEFINITE;
354 if (actual_mech_type)
355 *actual_mech_type = (gss_OID) gss_mech_dummy;
356
357 if (send_token == 1) {
358 sprintf(token_string, "%d", ret);
359
360 *output_token = make_dummy_token_msg(
361 token_string, strlen(token_string) + 1);
362 } else {
363 *output_token = make_dummy_token_msg(NULL, 0);
364 }
365
366 if (ret == GSS_S_COMPLETE)
367 ctx->established = 1;
368
369 ctx->last_stat = ret;
370 return (ret);
371 }
372
373 /*ARGSUSED*/
374 OM_uint32
dummy_gss_accept_sec_context(ct,minor_status,context_handle,verifier_cred_handle,input_token,input_chan_bindings,src_name,mech_type,output_token,ret_flags,time_rec,delegated_cred_handle)375 dummy_gss_accept_sec_context(ct, minor_status, context_handle,
376 verifier_cred_handle, input_token,
377 input_chan_bindings, src_name, mech_type,
378 output_token, ret_flags, time_rec,
379 delegated_cred_handle)
380 void *ct;
381 OM_uint32 *minor_status;
382 gss_ctx_id_t *context_handle;
383 gss_cred_id_t verifier_cred_handle;
384 gss_buffer_t input_token;
385 gss_channel_bindings_t input_chan_bindings;
386 gss_name_t *src_name;
387 gss_OID *mech_type;
388 gss_buffer_t output_token;
389 OM_uint32 *ret_flags;
390 OM_uint32 *time_rec;
391 gss_cred_id_t *delegated_cred_handle;
392 {
393 dummy_gss_ctx_id_t ctx;
394 char token_string[64];
395 gss_buffer_desc name;
396 OM_uint32 status;
397 gss_name_t temp;
398 unsigned char *ptr;
399 int bodysize;
400 int err;
401 OM_uint32 iret;
402 int return_token = 0;
403
404 dprintf("Entering accept_sec_context\n");
405
406 if (src_name)
407 *src_name = (gss_name_t)NULL;
408 output_token->length = 0;
409 output_token->value = NULL;
410 if (mech_type)
411 *mech_type = GSS_C_NULL_OID;
412 /* return a bogus cred handle */
413 if (delegated_cred_handle)
414 *delegated_cred_handle = GSS_C_NO_CREDENTIAL;
415
416 /* Check for defective input token. */
417 ptr = (unsigned char *) input_token->value;
418 if (err = g_verify_token_header((gss_OID)gss_mech_dummy, &bodysize,
419 &ptr, 0,
420 input_token->length)) {
421 *minor_status = err;
422 return (GSS_S_DEFECTIVE_TOKEN);
423 }
424
425 if (sscanf((char *)ptr, "%d", &iret) < 1) {
426 *minor_status = 1;
427 return (GSS_S_DEFECTIVE_TOKEN);
428 }
429
430 if (*context_handle == GSS_C_NO_CONTEXT) {
431 ctx = (dummy_gss_ctx_id_t)malloc(sizeof (dummy_gss_ctx_id_rec));
432 ctx->token_number = token_nums;
433 ctx->established = 0;
434 *context_handle = (gss_ctx_id_t)ctx;
435 } else {
436 ctx = (dummy_gss_ctx_id_t)(*context_handle);
437 }
438
439 if (ret_flags) /* user may pass a null pointer */
440 *ret_flags = dummy_flags;
441 if (time_rec) /* user may pass a null pointer */
442 *time_rec = GSS_C_INDEFINITE;
443 if (mech_type)
444 *mech_type = (gss_OID)gss_mech_dummy;
445
446 /*
447 * RFC 2078, page 36, under GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED
448 * tells us whether to return a token or not.
449 */
450
451 if (iret == GSS_S_CONTINUE_NEEDED)
452 return_token = 1;
453 else
454 return_token = 0;
455
456
457 if (ctx->token_number > 1) {
458 /*
459 * RFC 2078, page 36, under GSS_S_COMPLETE, says that if
460 * initiator is done, the target (us) has what it needs, so
461 * it must return GSS_S_COMPLETE;
462 */
463 if (iret == GSS_S_CONTINUE_NEEDED)
464 status = GSS_S_CONTINUE_NEEDED;
465 else
466 status = GSS_S_COMPLETE;
467
468 } else
469 status = GSS_S_COMPLETE;
470
471 /* source name is ready at GSS_S_COMPLELE */
472 if ((status == GSS_S_COMPLETE) && src_name) {
473 name.length = strlen(dummy_srcname);
474 name.value = dummy_srcname;
475 status = dummy_gss_import_name(ct, minor_status, &name,
476 (gss_OID)GSS_C_NT_USER_NAME, &temp);
477 if (status != GSS_S_COMPLETE) {
478 free(*context_handle);
479 *context_handle = GSS_C_NO_CONTEXT;
480 return (status);
481 }
482 *src_name = temp;
483 }
484
485 if (status == GSS_S_COMPLETE) {
486 ctx->established = 1;
487 }
488
489 if (return_token == 1) {
490 sprintf(token_string, "%d", status);
491
492 *output_token = make_dummy_token_msg(
493 token_string, strlen(token_string) + 1);
494 } else {
495 *output_token = make_dummy_token_msg(NULL, 0);
496 }
497
498 if (ctx->token_number > 0)
499 ctx->token_number--;
500
501 return (status);
502 }
503
504
505 /*ARGSUSED*/
506 OM_uint32
dummy_gss_process_context_token(ct,minor_status,context_handle,token_buffer)507 dummy_gss_process_context_token(ct, minor_status, context_handle, token_buffer)
508 void *ct;
509 OM_uint32 *minor_status;
510 gss_ctx_id_t context_handle;
511 gss_buffer_t token_buffer;
512 {
513 dprintf("In process_sec_context\n");
514 return (GSS_S_COMPLETE);
515 }
516
517 /*ARGSUSED*/
518 OM_uint32
dummy_gss_delete_sec_context(ct,minor_status,context_handle,output_token)519 dummy_gss_delete_sec_context(ct, minor_status, context_handle, output_token)
520 void *ct;
521 OM_uint32 *minor_status;
522 gss_ctx_id_t *context_handle;
523 gss_buffer_t output_token;
524 {
525 dummy_gss_ctx_id_t ctx;
526
527 dprintf("Entering delete_sec_context\n");
528
529 /* Make the length to 0, so the output token is not sent to peer */
530 if (output_token) {
531 output_token->length = 0;
532 output_token->value = NULL;
533 }
534
535 if (*context_handle == GSS_C_NO_CONTEXT) {
536 *minor_status = 0;
537 return (GSS_S_COMPLETE);
538 }
539
540 ctx = (dummy_gss_ctx_id_t)*context_handle;
541 free(ctx);
542 *context_handle = GSS_C_NO_CONTEXT;
543
544 dprintf("Leaving delete_sec_context\n");
545 return (GSS_S_COMPLETE);
546 }
547
548
549 /*ARGSUSED*/
550 OM_uint32
dummy_gss_context_time(ct,minor_status,context_handle,time_rec)551 dummy_gss_context_time(ct, minor_status, context_handle, time_rec)
552 void *ct;
553 OM_uint32 *minor_status;
554 gss_ctx_id_t context_handle;
555 OM_uint32 *time_rec;
556 {
557 dprintf("In context_time\n");
558 if (time_rec) /* user may pass a null pointer */
559 return (GSS_S_FAILURE);
560 else
561 *time_rec = GSS_C_INDEFINITE;
562 return (GSS_S_COMPLETE);
563 }
564
565 /*ARGSUSED*/
566 OM_uint32
dummy_gss_sign(ctx,minor_status,context_handle,qop_req,message_buffer,message_token)567 dummy_gss_sign(ctx, minor_status, context_handle,
568 qop_req, message_buffer, message_token)
569 void *ctx;
570 OM_uint32 *minor_status;
571 gss_ctx_id_t context_handle;
572 int qop_req;
573 gss_buffer_t message_buffer;
574 gss_buffer_t message_token;
575 {
576 char token_string[] = "dummy_gss_sign";
577 dummy_gss_ctx_id_t context;
578
579 dprintf("Entering gss_sign\n");
580
581 context = (dummy_gss_ctx_id_t)(context_handle);
582 if (context_handle == GSS_C_NO_CONTEXT)
583 return (GSS_S_NO_CONTEXT);
584 if (!context->established)
585 return (GSS_S_NO_CONTEXT);
586
587 *message_token = make_dummy_token_msg(
588 token_string, strlen(token_string));
589
590 dprintf("Leaving gss_sign\n");
591 return (GSS_S_COMPLETE);
592 }
593
594 /*ARGSUSED*/
595 OM_uint32
dummy_gss_verify(ctx,minor_status,context_handle,message_buffer,token_buffer,qop_state)596 dummy_gss_verify(ctx, minor_status, context_handle,
597 message_buffer, token_buffer, qop_state)
598 void *ctx;
599 OM_uint32 *minor_status;
600 gss_ctx_id_t context_handle;
601 gss_buffer_t message_buffer;
602 gss_buffer_t token_buffer;
603 int *qop_state;
604 {
605 unsigned char *ptr;
606 int bodysize;
607 int err;
608 dummy_gss_ctx_id_t context;
609
610 dprintf("Entering gss_verify\n");
611
612 context = (dummy_gss_ctx_id_t)(context_handle);
613 if (context_handle == GSS_C_NO_CONTEXT)
614 return (GSS_S_NO_CONTEXT);
615 if (!context->established)
616 return (GSS_S_NO_CONTEXT);
617
618 /* Check for defective input token. */
619 ptr = (unsigned char *) token_buffer->value;
620 if (err = g_verify_token_header((gss_OID)gss_mech_dummy, &bodysize,
621 &ptr, 0,
622 token_buffer->length)) {
623 *minor_status = err;
624 return (GSS_S_DEFECTIVE_TOKEN);
625 }
626
627 if (qop_state)
628 *qop_state = GSS_C_QOP_DEFAULT;
629
630 dprintf("Leaving gss_verify\n");
631 return (GSS_S_COMPLETE);
632 }
633
634 /*ARGSUSED*/
635 OM_uint32
dummy_gss_seal(ctx,minor_status,context_handle,conf_req_flag,qop_req,input_message_buffer,conf_state,output_message_buffer)636 dummy_gss_seal(ctx, minor_status, context_handle, conf_req_flag,
637 qop_req, input_message_buffer, conf_state,
638 output_message_buffer)
639 void *ctx;
640 OM_uint32 *minor_status;
641 gss_ctx_id_t context_handle;
642 int conf_req_flag;
643 int qop_req;
644 gss_buffer_t input_message_buffer;
645 int *conf_state;
646 gss_buffer_t output_message_buffer;
647 {
648 gss_buffer_desc output;
649 dummy_gss_ctx_id_t context;
650
651 dprintf("Entering gss_seal\n");
652
653 context = (dummy_gss_ctx_id_t)(context_handle);
654 if (context_handle == GSS_C_NO_CONTEXT)
655 return (GSS_S_NO_CONTEXT);
656 if (!context->established)
657 return (GSS_S_NO_CONTEXT);
658
659 /* Copy the input message to output message */
660 output = make_dummy_token_msg(
661 input_message_buffer->value, input_message_buffer->length);
662
663 if (conf_state)
664 *conf_state = 1;
665
666 *output_message_buffer = output;
667
668 dprintf("Leaving gss_seal\n");
669 return (GSS_S_COMPLETE);
670 }
671
672
673
674
675 /*ARGSUSED*/
676 OM_uint32
dummy_gss_unseal(ctx,minor_status,context_handle,input_message_buffer,output_message_buffer,conf_state,qop_state)677 dummy_gss_unseal(ctx, minor_status, context_handle,
678 input_message_buffer, output_message_buffer,
679 conf_state, qop_state)
680 void *ctx;
681 OM_uint32 *minor_status;
682 gss_ctx_id_t context_handle;
683 gss_buffer_t input_message_buffer;
684 gss_buffer_t output_message_buffer;
685 int *conf_state;
686 int *qop_state;
687 {
688 gss_buffer_desc output;
689 unsigned char *ptr;
690 int bodysize;
691 int err;
692 dummy_gss_ctx_id_t context;
693
694 dprintf("Entering gss_unseal\n");
695
696 context = (dummy_gss_ctx_id_t)(context_handle);
697 if (context_handle == GSS_C_NO_CONTEXT)
698 return (GSS_S_NO_CONTEXT);
699 if (!context->established)
700 return (GSS_S_NO_CONTEXT);
701
702 ptr = (unsigned char *) input_message_buffer->value;
703 if (err = g_verify_token_header((gss_OID)gss_mech_dummy, &bodysize,
704 &ptr, 0,
705 input_message_buffer->length)) {
706 *minor_status = err;
707 return (GSS_S_DEFECTIVE_TOKEN);
708 }
709 output.length = bodysize;
710 output.value = (void *)malloc(output.length);
711 memcpy(output.value, ptr, output.length);
712
713 *output_message_buffer = output;
714 if (qop_state)
715 *qop_state = GSS_C_QOP_DEFAULT;
716 if (conf_state)
717 *conf_state = 1;
718
719 dprintf("Leaving gss_unseal\n");
720 return (GSS_S_COMPLETE);
721 }
722
723 /*ARGSUSED*/
724 OM_uint32
dummy_gss_display_status(ctx,minor_status,status_value,status_type,mech_type,message_context,status_string)725 dummy_gss_display_status(ctx, minor_status, status_value, status_type,
726 mech_type, message_context, status_string)
727 void *ctx;
728 OM_uint32 *minor_status;
729 OM_uint32 status_value;
730 int status_type;
731 gss_OID mech_type;
732 OM_uint32 *message_context;
733 gss_buffer_t status_string;
734 {
735 dprintf("Entering display_status\n");
736
737 *message_context = 0;
738 *status_string = make_dummy_token_buffer("dummy_gss_display_status");
739
740 dprintf("Leaving display_status\n");
741 return (GSS_S_COMPLETE);
742 }
743
744 /*ARGSUSED*/
745 OM_uint32
dummy_gss_indicate_mechs(ctx,minor_status,mech_set)746 dummy_gss_indicate_mechs(ctx, minor_status, mech_set)
747 void *ctx;
748 OM_uint32 *minor_status;
749 gss_OID_set *mech_set;
750 {
751 dprintf("Entering indicate_mechs\n");
752
753 *minor_status = 0;
754 if (mech_set) {
755 if (gss_copy_oid_set(minor_status, gss_mech_set_dummy,
756 mech_set) == GSS_S_FAILURE) {
757 return (GSS_S_FAILURE);
758 }
759 }
760
761 dprintf("Leaving indicate_mechs\n");
762 return (GSS_S_COMPLETE);
763 }
764
765 /*ARGSUSED*/
766 OM_uint32
dummy_gss_compare_name(ctx,minor_status,name1,name2,name_equal)767 dummy_gss_compare_name(ctx, minor_status, name1, name2, name_equal)
768 void *ctx;
769 OM_uint32 *minor_status;
770 gss_name_t name1;
771 gss_name_t name2;
772 int *name_equal;
773 {
774 dummy_name_t name_1 = (dummy_name_t)name1;
775 dummy_name_t name_2 = (dummy_name_t)name2;
776
777 dprintf("Entering compare_name\n");
778
779 if (g_OID_equal(name_1->type, name_2->type) &&
780 (name_1->buffer->length == name_2->buffer->length) &&
781 !memcmp(name_1->buffer->value, name_2->buffer->value,
782 name_1->buffer->length))
783 *name_equal = 1;
784 else
785 *name_equal = 0;
786
787 dprintf("Leaving compare_name\n");
788 return (GSS_S_COMPLETE);
789 }
790
791 /*ARGSUSED*/
792 OM_uint32
dummy_gss_display_name(ctx,minor_status,input_name,output_name_buffer,output_name_type)793 dummy_gss_display_name(ctx, minor_status, input_name, output_name_buffer,
794 output_name_type)
795 void *ctx;
796 OM_uint32 *minor_status;
797 gss_name_t input_name;
798 gss_buffer_t output_name_buffer;
799 gss_OID *output_name_type;
800 {
801 OM_uint32 status = GSS_S_COMPLETE;
802 dummy_name_t name = (dummy_name_t)input_name;
803
804 dprintf("Entering display_name\n");
805
806 if (g_OID_equal(name->type, GSS_C_NT_USER_NAME) ||
807 g_OID_equal(name->type, GSS_C_NT_MACHINE_UID_NAME) ||
808 g_OID_equal(name->type, GSS_C_NT_STRING_UID_NAME) ||
809 g_OID_equal(name->type, GSS_C_NT_HOSTBASED_SERVICE)) {
810 /*
811 * output_name_buffer = (gss_buffer_t)
812 * malloc(sizeof (gss_buffer_desc));
813 */
814 if (output_name_buffer == NULL)
815 return (GSS_S_FAILURE);
816
817 output_name_buffer->length = name->buffer->length;
818 output_name_buffer->value = (void *)
819 malloc(name->buffer->length);
820 if (output_name_buffer->value == NULL)
821 return (GSS_S_FAILURE);
822
823 memcpy(output_name_buffer->value, name->buffer->value,
824 name->buffer->length);
825 if (output_name_type)
826 *output_name_type = name->type;
827
828 dprintf("Leaving display_name\n");
829 return (status);
830 }
831
832 dprintf("Leaving display_name\n");
833 return (GSS_S_BAD_NAMETYPE);
834 }
835
836 /*ARGSUSED*/
837 OM_uint32
dummy_gss_import_name(ctx,minor_status,input_name_buffer,input_name_type,output_name)838 dummy_gss_import_name(ctx, minor_status, input_name_buffer,
839 input_name_type, output_name)
840 void *ctx;
841 OM_uint32 *minor_status;
842 gss_buffer_t input_name_buffer;
843 gss_OID input_name_type;
844 gss_name_t *output_name;
845 {
846 OM_uint32 status;
847
848 dprintf("Entering import_name\n");
849
850 *output_name = NULL;
851 *minor_status = 0;
852
853 if (input_name_type == GSS_C_NULL_OID)
854 return (GSS_S_BAD_NAMETYPE);
855
856 if (g_OID_equal(input_name_type, GSS_C_NT_USER_NAME) ||
857 g_OID_equal(input_name_type, GSS_C_NT_MACHINE_UID_NAME) ||
858 g_OID_equal(input_name_type, GSS_C_NT_STRING_UID_NAME) ||
859 g_OID_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE)) {
860 dummy_name_t name = (dummy_name_t)
861 malloc(sizeof (dummy_name_desc));
862 name->buffer = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
863 name->buffer->length = input_name_buffer->length;
864 name->buffer->value = (void *)malloc(input_name_buffer->length);
865 if (name->buffer->value == NULL)
866 return (GSS_S_FAILURE);
867
868 memcpy(name->buffer->value, input_name_buffer->value,
869 input_name_buffer->length);
870
871 status = generic_gss_copy_oid(minor_status,
872 input_name_type, &(name->type));
873 *output_name = (gss_name_t)name;
874 dprintf("Leaving import_name\n");
875 return (status);
876 }
877 dprintf("Leaving import_name\n");
878 return (GSS_S_BAD_NAMETYPE);
879 }
880
881 /*ARGSUSED*/
882 OM_uint32
dummy_gss_release_name(ctx,minor_status,input_name)883 dummy_gss_release_name(ctx, minor_status, input_name)
884 void *ctx;
885 OM_uint32 *minor_status;
886 gss_name_t *input_name;
887 {
888 dummy_name_t name = (dummy_name_t)*input_name;
889
890 dprintf("Entering release_name\n");
891 free(name->buffer->value);
892 generic_gss_release_oid(minor_status, &(name->type));
893 free(name->buffer);
894 free(name);
895 dprintf("Leaving release_name\n");
896 return (GSS_S_COMPLETE);
897 }
898
899 /*ARGSUSED*/
900 OM_uint32
dummy_gss_inquire_cred(ctx,minor_status,cred_handle,name,lifetime_ret,cred_usage,mechanisms)901 dummy_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
902 cred_usage, mechanisms)
903 void *ctx;
904 OM_uint32 *minor_status;
905 gss_cred_id_t cred_handle;
906 gss_name_t *name;
907 OM_uint32 *lifetime_ret;
908 gss_cred_usage_t *cred_usage;
909 gss_OID_set *mechanisms;
910 {
911 dprintf("Entering inquire_cred\n");
912 if (name)
913 *name = (gss_name_t)make_dummy_token
914 ("dummy gss credential");
915 if (lifetime_ret)
916 *lifetime_ret = GSS_C_INDEFINITE;
917 if (cred_usage)
918 *cred_usage = GSS_C_BOTH;
919 if (mechanisms) {
920 if (gss_copy_oid_set(minor_status, gss_mech_set_dummy,
921 mechanisms) == GSS_S_FAILURE)
922 return (GSS_S_FAILURE);
923 }
924
925 dprintf("Leaving inquire_cred\n");
926 return (GSS_S_COMPLETE);
927 }
928
929 /*ARGSUSED*/
930 OM_uint32
dummy_gss_add_cred(ctx,minor_status,input_cred_handle,desired_name,desired_mech,cred_usage,initiator_time_req,acceptor_time_req,output_cred_handle,actual_mechs,initiator_time_rec,acceptor_time_rec)931 dummy_gss_add_cred(ctx, minor_status, input_cred_handle,
932 desired_name, desired_mech, cred_usage,
933 initiator_time_req, acceptor_time_req,
934 output_cred_handle, actual_mechs,
935 initiator_time_rec, acceptor_time_rec)
936 void *ctx;
937 OM_uint32 *minor_status;
938 gss_cred_id_t input_cred_handle;
939 gss_name_t desired_name;
940 gss_OID desired_mech;
941 gss_cred_usage_t cred_usage;
942 OM_uint32 initiator_time_req;
943 OM_uint32 acceptor_time_req;
944 gss_cred_id_t *output_cred_handle;
945 gss_OID_set *actual_mechs;
946 OM_uint32 *initiator_time_rec;
947 OM_uint32 *acceptor_time_rec;
948 {
949 dprintf("Entering add_cred\n");
950
951 if ((desired_mech != GSS_C_NULL_OID) &&
952 (g_OID_equal(desired_mech, gss_mech_dummy)))
953 return (GSS_S_BAD_MECH);
954 *minor_status = 0;
955
956 dprintf("Leaving add_cred\n");
957
958 /* This routine likes in kerberos V5 is never be used / called by */
959 /* the GSS_API. It simply returns GSS_S_DUPLICATE_ELEMENT to indicate */
960 /* this error */
961
962 return (GSS_S_DUPLICATE_ELEMENT);
963 }
964
965 /* Should I add the token structure to deal with import/export */
966 /* of sec_context. For now, I just create dummy interprocess token, and when */
967 /* the peer accept it, it calls the import_sec_context.The import_sec_context */
968 /* creates new sec_context with status established. (rather than get it */
969 /* from interprocess token. it can be done because the sec context in dummy */
970 /* mechanism is very simple (contains only status if it's established). */
971 /*ARGSUSED*/
972 OM_uint32
dummy_gss_export_sec_context(ct,minor_status,context_handle,interprocess_token)973 dummy_gss_export_sec_context(ct, minor_status, context_handle,
974 interprocess_token)
975 void *ct;
976 OM_uint32 *minor_status;
977 gss_ctx_id_t *context_handle;
978 gss_buffer_t interprocess_token;
979 {
980 char str[] = "dummy_gss_export_sec_context";
981
982 dprintf("Entering export_sec_context\n");
983
984 *interprocess_token = make_dummy_token_msg(str, strlen(str));
985 free(*context_handle);
986 *context_handle = GSS_C_NO_CONTEXT;
987
988 dprintf("Leaving export_sec_context\n");
989 return (GSS_S_COMPLETE);
990 }
991
992 /*ARGSUSED*/
993 OM_uint32
dummy_gss_import_sec_context(ct,minor_status,interprocess_token,context_handle)994 dummy_gss_import_sec_context(ct, minor_status, interprocess_token,
995 context_handle)
996 void *ct;
997 OM_uint32 *minor_status;
998 gss_buffer_t interprocess_token;
999 gss_ctx_id_t *context_handle;
1000 {
1001 /* Assume that we got ctx from the interprocess token. */
1002 dummy_gss_ctx_id_t ctx;
1003
1004 dprintf("Entering import_sec_context\n");
1005
1006 ctx = (dummy_gss_ctx_id_t)malloc(sizeof (dummy_gss_ctx_id_rec));
1007 ctx->token_number = 0;
1008 ctx->established = 1;
1009
1010 *context_handle = (gss_ctx_id_t)ctx;
1011
1012 dprintf("Leaving import_sec_context\n");
1013 return (GSS_S_COMPLETE);
1014 }
1015
1016 /*ARGSUSED*/
1017 OM_uint32
dummy_gss_inquire_cred_by_mech(ctx,minor_status,cred_handle,mech_type,name,initiator_lifetime,acceptor_lifetime,cred_usage)1018 dummy_gss_inquire_cred_by_mech(ctx, minor_status, cred_handle,
1019 mech_type, name, initiator_lifetime,
1020 acceptor_lifetime, cred_usage)
1021 void *ctx;
1022 OM_uint32 *minor_status;
1023 gss_cred_id_t cred_handle;
1024 gss_OID mech_type;
1025 gss_name_t *name;
1026 OM_uint32 *initiator_lifetime;
1027 OM_uint32 *acceptor_lifetime;
1028 gss_cred_usage_t *cred_usage;
1029 {
1030 dprintf("Entering inquire_cred_by_mech\n");
1031 if (name)
1032 *name = (gss_name_t)make_dummy_token("dummy credential name");
1033 if (initiator_lifetime)
1034 *initiator_lifetime = GSS_C_INDEFINITE;
1035 if (acceptor_lifetime)
1036 *acceptor_lifetime = GSS_C_INDEFINITE;
1037 if (cred_usage)
1038 *cred_usage = GSS_C_BOTH;
1039
1040 dprintf("Leaving inquire_cred_by_mech\n");
1041 return (GSS_S_COMPLETE);
1042 }
1043
1044 /*ARGSUSED*/
1045 OM_uint32
dummy_gss_inquire_names_for_mech(ctx,minor_status,mechanism,name_types)1046 dummy_gss_inquire_names_for_mech(ctx, minor_status, mechanism, name_types)
1047 void *ctx;
1048 OM_uint32 *minor_status;
1049 gss_OID mechanism;
1050 gss_OID_set *name_types;
1051 {
1052 OM_uint32 major, minor;
1053
1054 dprintf("Entering inquire_names_for_mech\n");
1055 /*
1056 * We only know how to handle our own mechanism.
1057 */
1058 if ((mechanism != GSS_C_NULL_OID) &&
1059 !g_OID_equal(gss_mech_dummy, mechanism)) {
1060 *minor_status = 0;
1061 return (GSS_S_FAILURE);
1062 }
1063
1064 major = gss_create_empty_oid_set(minor_status, name_types);
1065 if (major == GSS_S_COMPLETE) {
1066 /* Now add our members. */
1067 if (((major = gss_add_oid_set_member(minor_status,
1068 (gss_OID) GSS_C_NT_USER_NAME, name_types))
1069 == GSS_S_COMPLETE) &&
1070 ((major = gss_add_oid_set_member(minor_status,
1071 (gss_OID) GSS_C_NT_MACHINE_UID_NAME, name_types))
1072 == GSS_S_COMPLETE) &&
1073 ((major = gss_add_oid_set_member(minor_status,
1074 (gss_OID) GSS_C_NT_STRING_UID_NAME, name_types))
1075 == GSS_S_COMPLETE)) {
1076 major = gss_add_oid_set_member(minor_status,
1077 (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, name_types);
1078 }
1079
1080 if (major != GSS_S_COMPLETE)
1081 (void) gss_release_oid_set(&minor, name_types);
1082 }
1083
1084 dprintf("Leaving inquire_names_for_mech\n");
1085 return (major);
1086 }
1087
1088 /*ARGSUSED*/
1089 OM_uint32
dummy_gss_inquire_context(ct,minor_status,context_handle,initiator_name,acceptor_name,lifetime_rec,mech_type,ret_flags,locally_initiated,open)1090 dummy_gss_inquire_context(ct, minor_status, context_handle, initiator_name,
1091 acceptor_name, lifetime_rec, mech_type, ret_flags,
1092 locally_initiated, open)
1093 void *ct;
1094 OM_uint32 *minor_status;
1095 gss_ctx_id_t context_handle;
1096 gss_name_t *initiator_name;
1097 gss_name_t *acceptor_name;
1098 OM_uint32 *lifetime_rec;
1099 gss_OID *mech_type;
1100 OM_uint32 *ret_flags;
1101 int *locally_initiated;
1102 int *open;
1103 {
1104 dummy_gss_ctx_id_t ctx;
1105 dummy_name_t name1, name2;
1106 OM_uint32 status;
1107
1108 dprintf("Entering inquire_context\n");
1109
1110 ctx = (dummy_gss_ctx_id_t)(context_handle);
1111 name1 = (dummy_name_t)
1112 malloc(sizeof (dummy_name_desc));
1113 name1->buffer = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
1114 name1->buffer->length = dummy_context_name_len;
1115 name1->buffer->value = make_dummy_token("dummy context name");
1116 status = generic_gss_copy_oid(minor_status,
1117 (gss_OID) GSS_C_NT_USER_NAME, &(name1->type));
1118 if (status != GSS_S_COMPLETE)
1119 return (status);
1120 if (initiator_name)
1121 *initiator_name = (gss_name_t)name1;
1122
1123 name2 = (dummy_name_t)
1124 malloc(sizeof (dummy_name_desc));
1125 name2->buffer = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
1126 name2->buffer->length = dummy_context_name_len;
1127 name2->buffer->value = make_dummy_token("dummy context name");
1128 status = generic_gss_copy_oid(minor_status,
1129 (gss_OID) GSS_C_NT_USER_NAME, &(name2->type));
1130 if (status != GSS_S_COMPLETE)
1131 return (status);
1132 if (acceptor_name)
1133 *acceptor_name = (gss_name_t)name2;
1134
1135 if (lifetime_rec) /* user may pass a null pointer */
1136 *lifetime_rec = GSS_C_INDEFINITE;
1137 if (mech_type)
1138 *mech_type = (gss_OID)gss_mech_dummy;
1139 if (ret_flags)
1140 *ret_flags = dummy_flags;
1141 if (open)
1142 *open = ctx->established;
1143
1144 dprintf("Leaving inquire_context\n");
1145 return (GSS_S_COMPLETE);
1146 }
1147
1148 /*ARGSUSED*/
1149 OM_uint32
dummy_gss_internal_release_oid(ct,minor_status,oid)1150 dummy_gss_internal_release_oid(ct, minor_status, oid)
1151 void *ct;
1152 OM_uint32 *minor_status;
1153 gss_OID *oid;
1154 {
1155 dprintf("Entering internal_release_oid\n");
1156
1157 /* Similar to krb5_gss_internal_release_oid */
1158
1159 if (*oid != gss_mech_dummy)
1160 return (GSS_S_CONTINUE_NEEDED); /* We don't know this oid */
1161
1162 *minor_status = 0;
1163 *oid = GSS_C_NO_OID;
1164
1165 dprintf("Leaving internal_release_oid\n");
1166 return (GSS_S_COMPLETE);
1167 }
1168
1169 /*ARGSUSED*/
1170 OM_uint32
dummy_gss_wrap_size_limit(ct,minor_status,context_handle,conf_req_flag,qop_req,req_output_size,max_input_size)1171 dummy_gss_wrap_size_limit(ct, minor_status, context_handle, conf_req_flag,
1172 qop_req, req_output_size, max_input_size)
1173 void *ct;
1174 OM_uint32 *minor_status;
1175 gss_ctx_id_t context_handle;
1176 int conf_req_flag;
1177 gss_qop_t qop_req;
1178 OM_uint32 req_output_size;
1179 OM_uint32 *max_input_size;
1180 {
1181 dprintf("Entering wrap_size_limit\n");
1182 *max_input_size = req_output_size;
1183 dprintf("Leaving wrap_size_limit\n");
1184 return (GSS_S_COMPLETE);
1185 }
1186
1187 /* ARGSUSED */
1188 OM_uint32
dummy_pname_to_uid(ct,minor_status,name,uidOut)1189 dummy_pname_to_uid(ct, minor_status, name, uidOut)
1190 void *ct;
1191 OM_uint32 *minor_status;
1192 const gss_name_t name;
1193 uid_t *uidOut;
1194 {
1195 dprintf("Entering pname_to_uid\n");
1196 *minor_status = 0;
1197 *uidOut = 60001;
1198 dprintf("Leaving pname_to_uid\n");
1199 return (GSS_S_COMPLETE);
1200 }
1201
1202 static dummy_token_t
make_dummy_token(char * name)1203 make_dummy_token(char *name)
1204 {
1205 dummy_token_t token;
1206
1207 token = (dummy_token_t)malloc(strlen(name)+1);
1208 strcpy(token, name);
1209 return (token);
1210 }
1211
1212 static void
free_dummy_token(dummy_token_t * token)1213 free_dummy_token(dummy_token_t *token)
1214 {
1215 free(*token);
1216 *token = NULL;
1217 }
1218
1219 static gss_buffer_desc
make_dummy_token_buffer(char * name)1220 make_dummy_token_buffer(char *name)
1221 {
1222 gss_buffer_desc buffer;
1223
1224 if (name == NULL) {
1225 buffer.length = 0;
1226 buffer.value = NULL;
1227 } else {
1228 buffer.length = strlen(name)+1;
1229 buffer.value = make_dummy_token(name);
1230 }
1231 return (buffer);
1232 }
1233
1234 static gss_buffer_desc
make_dummy_token_msg(void * data,int dataLen)1235 make_dummy_token_msg(void *data, int dataLen)
1236 {
1237 gss_buffer_desc buffer;
1238 int tlen;
1239 unsigned char *t;
1240 unsigned char *ptr;
1241
1242 if (data == NULL) {
1243 buffer.length = 0;
1244 buffer.value = NULL;
1245 return (buffer);
1246 }
1247
1248 tlen = g_token_size((gss_OID)gss_mech_dummy, dataLen);
1249 t = (unsigned char *) malloc(tlen);
1250 ptr = t;
1251
1252 g_make_token_header((gss_OID)gss_mech_dummy, dataLen, &ptr, 0);
1253 memcpy(ptr, data, dataLen);
1254
1255 buffer.length = tlen;
1256 buffer.value = (void *) t;
1257 return (buffer);
1258 }
1259
1260 static int
der_length_size(length)1261 der_length_size(length)
1262 int length;
1263 {
1264 if (length < (1<<7))
1265 return (1);
1266 else if (length < (1<<8))
1267 return (2);
1268 else if (length < (1<<16))
1269 return (3);
1270 else if (length < (1<<24))
1271 return (4);
1272 else
1273 return (5);
1274 }
1275
1276 static void
der_write_length(buf,length)1277 der_write_length(buf, length)
1278 unsigned char **buf;
1279 int length;
1280 {
1281 if (length < (1<<7)) {
1282 *(*buf)++ = (unsigned char) length;
1283 } else {
1284 *(*buf)++ = (unsigned char) (der_length_size(length)+127);
1285 if (length >= (1<<24))
1286 *(*buf)++ = (unsigned char) (length>>24);
1287 if (length >= (1<<16))
1288 *(*buf)++ = (unsigned char) ((length>>16)&0xff);
1289 if (length >= (1<<8))
1290 *(*buf)++ = (unsigned char) ((length>>8)&0xff);
1291 *(*buf)++ = (unsigned char) (length&0xff);
1292 }
1293 }
1294
1295 static int
der_read_length(buf,bufsize)1296 der_read_length(buf, bufsize)
1297 unsigned char **buf;
1298 int *bufsize;
1299 {
1300 unsigned char sf;
1301 int ret;
1302
1303 if (*bufsize < 1)
1304 return (-1);
1305
1306 sf = *(*buf)++;
1307 (*bufsize)--;
1308 if (sf & 0x80) {
1309 if ((sf &= 0x7f) > ((*bufsize)-1))
1310 return (-1);
1311
1312 if (sf > DUMMY_SIZE_OF_INT)
1313 return (-1);
1314 ret = 0;
1315 for (; sf; sf--) {
1316 ret = (ret<<8) + (*(*buf)++);
1317 (*bufsize)--;
1318 }
1319 } else {
1320 ret = sf;
1321 }
1322
1323 return (ret);
1324 }
1325
1326 static int
g_token_size(mech,body_size)1327 g_token_size(mech, body_size)
1328 gss_OID mech;
1329 unsigned int body_size;
1330 {
1331 /* set body_size to sequence contents size */
1332 body_size += 4 + (int)mech->length; /* NEED overflow check */
1333 return (1 + der_length_size(body_size) + body_size);
1334 }
1335
1336 static void
g_make_token_header(mech,body_size,buf,tok_type)1337 g_make_token_header(mech, body_size, buf, tok_type)
1338 gss_OID mech;
1339 int body_size;
1340 unsigned char **buf;
1341 int tok_type;
1342 {
1343 *(*buf)++ = 0x60;
1344 der_write_length(buf, 4 + mech->length + body_size);
1345 *(*buf)++ = 0x06;
1346 *(*buf)++ = (unsigned char) mech->length;
1347 TWRITE_STR(*buf, mech->elements, ((int)mech->length));
1348 *(*buf)++ = (unsigned char) ((tok_type>>8)&0xff);
1349 *(*buf)++ = (unsigned char) (tok_type&0xff);
1350 }
1351
1352 static int
g_verify_token_header(mech,body_size,buf_in,tok_type,toksize)1353 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize)
1354 gss_OID mech;
1355 int *body_size;
1356 unsigned char **buf_in;
1357 int tok_type;
1358 int toksize;
1359 {
1360 unsigned char *buf = *buf_in;
1361 int seqsize;
1362 gss_OID_desc toid;
1363 int ret = 0;
1364
1365 if ((toksize -= 1) < 0)
1366 return (G_BAD_TOK_HEADER);
1367 if (*buf++ != 0x60)
1368 return (G_BAD_TOK_HEADER);
1369
1370 if ((seqsize = der_read_length(&buf, &toksize)) < 0)
1371 return (G_BAD_TOK_HEADER);
1372
1373 if (seqsize != toksize)
1374 return (G_BAD_TOK_HEADER);
1375
1376 if ((toksize -= 1) < 0)
1377 return (G_BAD_TOK_HEADER);
1378 if (*buf++ != 0x06)
1379 return (G_BAD_TOK_HEADER);
1380
1381 if ((toksize -= 1) < 0)
1382 return (G_BAD_TOK_HEADER);
1383 toid.length = *buf++;
1384
1385 if ((toksize -= toid.length) < 0)
1386 return (G_BAD_TOK_HEADER);
1387 toid.elements = buf;
1388 buf += toid.length;
1389
1390 if (!g_OID_equal(&toid, mech))
1391 ret = G_WRONG_MECH;
1392
1393 /*
1394 * G_WRONG_MECH is not returned immediately because it's more important
1395 * to return G_BAD_TOK_HEADER if the token header is in fact bad
1396 */
1397
1398 if ((toksize -= 2) < 0)
1399 return (G_BAD_TOK_HEADER);
1400
1401 if ((*buf++ != ((tok_type>>8)&0xff)) ||
1402 (*buf++ != (tok_type&0xff)))
1403 return (G_BAD_TOK_HEADER);
1404
1405 if (!ret) {
1406 *buf_in = buf;
1407 *body_size = toksize;
1408 }
1409
1410 return (ret);
1411 }
1412