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