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