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 }