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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1229 free_dummy_token(dummy_token_t *token) 1230 { 1231 free(*token); 1232 *token = NULL; 1233 } 1234 1235 static gss_buffer_desc 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 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 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 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 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 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 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 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