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