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