static OM_uint32
send_error_token(OM_uint32 *minor_status,
		 krb5_context context,
		 krb5_error_code kret,
		 krb5_principal server,
		 krb5_data *indata,
		 gss_OID mech,
		 gss_buffer_t output_token)
{
    krb5_principal ap_req_server = NULL;
    krb5_error_code ret;
    OM_uint32 maj_stat;
    /* this e_data value encodes KERB_AP_ERR_TYPE_SKEW_RECOVERY which
       tells windows to try again with the corrected timestamp. See
       [MS-KILE] 2.2.1 KERB-ERROR-DATA */
    krb5_data e_data = { 7, rk_UNCONST("\x30\x05\xa1\x03\x02\x01\x02") };

    /* build server from request if the acceptor had not selected one */
    if (server == NULL && indata) {
	AP_REQ ap_req;

	ret = krb5_decode_ap_req(context, indata, &ap_req);
	if (ret) {
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}
	ret = _krb5_principalname2krb5_principal(context,
						  &ap_req_server,
						  ap_req.ticket.sname,
						  ap_req.ticket.realm);
	free_AP_REQ(&ap_req);
	if (ret) {
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}
	server = ap_req_server;
    }

    maj_stat = _gsskrb5_error_token(minor_status, mech, context, kret,
				    &e_data, server,  output_token);
    if (ap_req_server)
	krb5_free_principal(context, ap_req_server);
    if (maj_stat) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    *minor_status = 0;
    return GSS_S_CONTINUE_NEEDED;
}
Beispiel #2
0
static OM_uint32
iakerb_acceptor_start(OM_uint32 * minor_status,
		      gsskrb5_ctx ctx,
		      krb5_context context,
		      const gss_cred_id_t acceptor_cred_handle,
		      const gss_buffer_t input_token_buffer,
		      const gss_channel_bindings_t input_chan_bindings,
		      gss_name_t * src_name,
		      gss_OID * mech_type,
		      gss_buffer_t output_token,
		      OM_uint32 * ret_flags,
		      OM_uint32 * time_rec,
		      gss_cred_id_t * delegated_cred_handle)
{
    krb5_data indata, outdata;
    gss_buffer_desc idata;
    krb5_error_code kret;
    heim_ipc ictx;
    OM_uint32 ret;
    
    if (ctx->messages == NULL) {
	ctx->messages = krb5_storage_emem();
	if (ctx->messages == NULL) {
	    *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	}
    }
    
    ret = _gsskrb5_iakerb_parse_header(minor_status, context, ctx, input_token_buffer, &indata);
    if (ret == GSS_S_DEFECTIVE_TOKEN) {
	ctx->acceptor_state = gsskrb5_acceptor_start;
	return GSS_S_COMPLETE;
    } else if (ret != GSS_S_COMPLETE)
	return ret;
    
    krb5_storage_write(ctx->messages,
		       input_token_buffer->value,
		       input_token_buffer->length);
    
    idata.value = indata.data;
    idata.length = indata.length;
    
    heim_assert(ctx->iakerbrealm != NULL, "realm not set by decoder, non OPT value");
    
    if (krb5_realm_is_lkdc(ctx->iakerbrealm)) {
	
	kret = heim_ipc_init_context("ANY:org.h5l.kdc", &ictx);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}
	
	kret = heim_ipc_call(ictx, &indata, &outdata, NULL);
	heim_ipc_free_context(ictx);
	if (kret) {
	    _gsskrb5_error_token(minor_status, ctx->mech, context, kret,
				 NULL, NULL, output_token);
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	ret = _gsskrb5_iakerb_make_header(minor_status, context, ctx, ctx->iakerbrealm, &outdata, output_token);
	heim_ipc_free_data(&outdata);
	if (ret)
	    return ret;

    } else {
	/* XXX dont support non local realms right now */
	*minor_status = EINVAL;
	return GSS_S_FAILURE;
    }
    
    krb5_storage_write(ctx->messages,
		       output_token->value,
		       output_token->length);
    
    return GSS_S_CONTINUE_NEEDED;
}