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