コード例 #1
0
static OM_uint32
spnego_initial
           (OM_uint32 * minor_status,
	    gssspnego_cred cred,
            gss_ctx_id_t * context_handle,
            const gss_name_t target_name,
            const gss_OID mech_type,
            OM_uint32 req_flags,
            OM_uint32 time_req,
            const gss_channel_bindings_t input_chan_bindings,
            const gss_buffer_t input_token,
            gss_OID * actual_mech_type,
            gss_buffer_t output_token,
            OM_uint32 * ret_flags,
            OM_uint32 * time_rec
    )
{
    NegTokenInit ni;
    int ret;
    OM_uint32 sub, minor;
    gss_buffer_desc mech_token;
    u_char *buf;
    size_t buf_size, buf_len;
    gss_buffer_desc data;
    size_t ni_len;
    gss_ctx_id_t context;
    gssspnego_ctx ctx;
    spnego_name name = (spnego_name)target_name;

    *minor_status = 0;

    memset (&ni, 0, sizeof(ni));

    *context_handle = GSS_C_NO_CONTEXT;

    if (target_name == GSS_C_NO_NAME)
	return GSS_S_BAD_NAME;

    sub = _gss_spnego_alloc_sec_context(&minor, &context);
    if (GSS_ERROR(sub)) {
	*minor_status = minor;
	return sub;
    }
    ctx = (gssspnego_ctx)context;

    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);

    ctx->local = 1;

    sub = gss_import_name(&minor, &name->value, &name->type, &ctx->target_name);
    if (GSS_ERROR(sub)) {
	*minor_status = minor;
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }

    sub = _gss_spnego_indicate_mechtypelist(&minor,
					    ctx->target_name,
					    initiator_approved,
					    0,
					    cred,
					    &ni.mechTypes,
					    &ctx->preferred_mech_type);
    if (GSS_ERROR(sub)) {
	*minor_status = minor;
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }

    ni.reqFlags = NULL;

    /*
     * If we have a credential handle, use it to select the mechanism
     * that we will use
     */

    /* generate optimistic token */
    sub = gss_init_sec_context(&minor,
			       (cred != NULL) ? cred->negotiated_cred_id :
			          GSS_C_NO_CREDENTIAL,
			       &ctx->negotiated_ctx_id,
			       ctx->target_name,
			       ctx->preferred_mech_type,
			       req_flags,
			       time_req,
			       input_chan_bindings,
			       input_token,
			       &ctx->negotiated_mech_type,
			       &mech_token,
			       &ctx->mech_flags,
			       &ctx->mech_time_rec);
    if (GSS_ERROR(sub)) {
	free_NegTokenInit(&ni);
	*minor_status = minor;
	gss_mg_collect_error(ctx->preferred_mech_type, sub, minor);
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }
    if (sub == GSS_S_COMPLETE)
	ctx->maybe_open = 1;

    if (mech_token.length != 0) {
	ALLOC(ni.mechToken, 1);
	if (ni.mechToken == NULL) {
	    free_NegTokenInit(&ni);
	    gss_release_buffer(&minor, &mech_token);
	    _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	    *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	}
	ni.mechToken->length = mech_token.length;
	ni.mechToken->data = malloc(mech_token.length);
	if (ni.mechToken->data == NULL && mech_token.length != 0) {
	    free_NegTokenInit(&ni);
	    gss_release_buffer(&minor, &mech_token);
	    *minor_status = ENOMEM;
	    _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	    return GSS_S_FAILURE;
	}
	memcpy(ni.mechToken->data, mech_token.value, mech_token.length);
	gss_release_buffer(&minor, &mech_token);
    } else
	ni.mechToken = NULL;

    ni.mechListMIC = NULL;

    ni_len = length_NegTokenInit(&ni);
    buf_size = 1 + der_length_len(ni_len) + ni_len;

    buf = malloc(buf_size);
    if (buf == NULL) {
	free_NegTokenInit(&ni);
	*minor_status = ENOMEM;
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return GSS_S_FAILURE;
    }

    ret = encode_NegTokenInit(buf + buf_size - 1,
			      ni_len,
			      &ni, &buf_len);
    if (ret == 0 && ni_len != buf_len)
	abort();

    if (ret == 0) {
	size_t tmp;

	ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
				     buf_size - buf_len,
				     buf_len,
				     ASN1_C_CONTEXT,
				     CONS,
				     0,
				     &tmp);
	if (ret == 0 && tmp + buf_len != buf_size)
	    abort();
    }
    if (ret) {
	*minor_status = ret;
	free(buf);
	free_NegTokenInit(&ni);
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return GSS_S_FAILURE;
    }

    data.value  = buf;
    data.length = buf_size;

    ctx->initiator_mech_types.len = ni.mechTypes.len;
    ctx->initiator_mech_types.val = ni.mechTypes.val;
    ni.mechTypes.len = 0;
    ni.mechTypes.val = NULL;

    free_NegTokenInit(&ni);

    sub = gss_encapsulate_token(&data,
				GSS_SPNEGO_MECHANISM,
				output_token);
    free (buf);

    if (sub) {
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }

    if (actual_mech_type)
	*actual_mech_type = ctx->negotiated_mech_type;
    if (ret_flags)
	*ret_flags = ctx->mech_flags;
    if (time_rec)
	*time_rec = ctx->mech_time_rec;

    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);

    *context_handle = context;

    return GSS_S_CONTINUE_NEEDED;
}
コード例 #2
0
OM_uint32 KRB5_LIB_FUNCTION gss_init_sec_context_spnego(
	    OM_uint32 * minor_status,
            const gss_cred_id_t initiator_cred_handle,
            gss_ctx_id_t * context_handle,
            const gss_name_t target_name,
            const gss_OID mech_type,
            OM_uint32 req_flags,
            OM_uint32 time_req,
            const gss_channel_bindings_t input_chan_bindings,
            const gss_buffer_t input_token,
            gss_OID * actual_mech_type,
            gss_buffer_t output_token,
            OM_uint32 * ret_flags,
            OM_uint32 * time_rec)
{
   NegTokenInit token_init;
   OM_uint32 major_status, minor_status2;
   gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
   unsigned char *buf = NULL;
   size_t buf_size;
   size_t len;
   int ret;

   memset(&token_init, 0, sizeof(token_init));

   ALLOC(token_init.mechTypes);
   if (token_init.mechTypes == NULL) {
      *minor_status = ENOMEM;
      return GSS_S_FAILURE;
   }

   ret = add_mech(token_init.mechTypes, GSS_KRB5_MECH);
   if (ret) {
      *minor_status = ret;
      ret = GSS_S_FAILURE;
      goto end;
   }

#if 0
   ALLOC(token_init.reqFlags);
   if (token_init.reqFlags == NULL) {
      *minor_status = ENOMEM;
      ret = GSS_S_FAILURE;
      goto end;
   }
   set_context_flags(req_flags, token_init.reqFlags);
#endif

  major_status = gss_init_sec_context(minor_status,
	 			       initiator_cred_handle,
				       context_handle,
				       target_name,
				       GSS_KRB5_MECH,
				       req_flags,
				       time_req,
				       input_chan_bindings,
				       input_token,
				       actual_mech_type,
				       &krb5_output_token,
				       ret_flags,
				       time_rec);
  if (GSS_ERROR(major_status)) {
    ret = major_status;
    goto end;
  }
  if (krb5_output_token.length > 0) {
    printf("\nOK COUCOU INITSECCONTEXT L:117\n\n");
    ALLOC(token_init.mechToken);
    if (token_init.mechToken == NULL) {
      *minor_status = ENOMEM;
      ret = GSS_S_FAILURE;
      goto end;
    }
    token_init.mechToken->data = krb5_output_token.value;
    token_init.mechToken->length = krb5_output_token.length;
    krb5_output_token.length = 0; /* don't free it later */
  }
  printf("\nOK COUCOU INITSECCONTEXT L:128\n\n");

   /* The MS implementation of SPNEGO seems to not like the mechListMIC field,
    * so we omit it (it's optional anyway) */

  buf_size = 1024;
  buf = malloc(buf_size);

  do {
    ret = encode_NegTokenInit(buf + buf_size -1,
				  buf_size,
				  &token_init, &len);
    if (ret == 0) {
      size_t tmp;
      ret = der_put_length_and_tag(buf + buf_size - len - 1,
					 buf_size - len,
					 len,
					 KERB_CTXT,
					 CONS,
					 0,
					 &tmp);
      if (ret == 0) len += tmp;
      printf("\nOK COUCOU INITSECCONTEXT L:150\n\n");
    }
    if (ret) {
      if (ret == ASN1_OVERFLOW) {
        u_char *tmp;
        buf_size *= 2;
        tmp = realloc (buf, buf_size);
        if (tmp == NULL) {
          *minor_status = ENOMEM;
          ret = GSS_S_FAILURE;
          goto end;
        }
        buf = tmp;
        printf("\nOK COUCOU INITSECCONTEXT L:163\n\n");
      }
      else {
        *minor_status = ret;
        printf("\nOK COUCOU INITSECCONTEXT L:167\n\n");
        ret = GSS_S_FAILURE;
        goto end;
      }
    }
  } while (ret == ASN1_OVERFLOW);

  ret = gssapi_spnego_encapsulate(minor_status, buf + buf_size - len, len, output_token, GSS_SPNEGO_MECH);
  ret = major_status;

end:
  free_NegTokenInit(&token_init);
  if (krb5_output_token.length > 0)
    gss_release_buffer(&minor_status2, &krb5_output_token);
    if (buf)
      free(buf);
   return ret;
}