Exemple #1
0
static OM_uint32
gsskrb5_acceptor_ready(OM_uint32 * minor_status,
		       gsskrb5_ctx ctx,
		       krb5_context context,
		       gss_cred_id_t *delegated_cred_handle)
{
    OM_uint32 ret;
    int32_t seq_number;
    int is_cfx = 0;

    krb5_auth_con_getremoteseqnumber (context,
				      ctx->auth_context,
				      &seq_number);

    _gsskrb5i_is_cfx(context, ctx, 1);
    is_cfx = (ctx->more_flags & IS_CFX);

    ret = _gssapi_msg_order_create(minor_status,
				   &ctx->gk5c.order,
				   _gssapi_msg_order_f(ctx->flags),
				   seq_number, 0, is_cfx);
    if (ret)
	return ret;

    /*
     * If requested, set local sequence num to remote sequence if this
     * isn't a mutual authentication context
     */
    if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) {
	krb5_auth_con_setlocalseqnumber(context,
					ctx->auth_context,
					seq_number);
    }

    /*
     * We should handle the delegation ticket, in case it's there
     */
    if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) {
	ret = gsskrb5_accept_delegated_token(minor_status,
					     ctx,
					     context,
					     delegated_cred_handle);
	if (ret)
	    return ret;
    } else {
	/* Well, looks like it wasn't there after all */
	ctx->flags &= ~GSS_C_DELEG_FLAG;
    }

    ctx->acceptor_state = step_acceptor_completed;

    ctx->more_flags |= OPEN;

    return GSS_S_COMPLETE;
}
Exemple #2
0
static void
test_ap(krb5_context context,
	krb5_principal target,
	krb5_principal server,
	krb5_keytab keytab,
	krb5_ccache ccache,
	const krb5_flags client_flags)
{
    krb5_error_code ret;
    krb5_auth_context client_ac = NULL, server_ac = NULL;
    krb5_data data;
    krb5_flags server_flags;
    krb5_ticket *ticket = NULL;
    int32_t server_seq, client_seq;

    ret = krb5_mk_req_exact(context,
			    &client_ac,
			    client_flags,
			    target,
			    NULL,
			    ccache,
			    &data);
    if (ret)
	krb5_err(context, 1, ret, "krb5_mk_req_exact");

    ret = krb5_rd_req(context,
		      &server_ac,
		      &data,
		      server,
		      keytab,
		      &server_flags,
		      &ticket);
    if (ret)
	krb5_err(context, 1, ret, "krb5_rd_req");


    if (server_flags & AP_OPTS_MUTUAL_REQUIRED) {
	krb5_ap_rep_enc_part *repl;

	krb5_data_free(&data);

	if ((client_flags & AP_OPTS_MUTUAL_REQUIRED) == 0)
	    krb5_errx(context, 1, "client flag missing mutual req");

	ret = krb5_mk_rep (context, server_ac, &data);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_mk_rep");

	ret = krb5_rd_rep (context,
			   client_ac,
			   &data,
			   &repl);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_rd_rep");

	krb5_free_ap_rep_enc_part (context, repl);
    } else {
	if (client_flags & AP_OPTS_MUTUAL_REQUIRED)
	    krb5_errx(context, 1, "server flag missing mutual req");
    }

    krb5_auth_con_getremoteseqnumber(context, server_ac, &server_seq);
    krb5_auth_con_getremoteseqnumber(context, client_ac, &client_seq);
    if (server_seq != client_seq)
	krb5_errx(context, 1, "seq num differ");

    krb5_auth_con_getlocalseqnumber(context, server_ac, &server_seq);
    krb5_auth_con_getlocalseqnumber(context, client_ac, &client_seq);
    if (server_seq != client_seq)
	krb5_errx(context, 1, "seq num differ");

    krb5_data_free(&data);
    krb5_auth_con_free(context, client_ac);
    krb5_auth_con_free(context, server_ac);

    if (verify_pac) {
	krb5_pac pac;

	ret = krb5_ticket_get_authorization_data_type(context,
						      ticket,
						      KRB5_AUTHDATA_WIN2K_PAC,
						      &data);
	if (ret)
	    krb5_err(context, 1, ret, "get pac");

	ret = krb5_pac_parse(context, data.data, data.length, &pac);
	if (ret)
	    krb5_err(context, 1, ret, "pac parse");

	krb5_pac_free(context, pac);
    }

    krb5_free_ticket(context, ticket);
}
static OM_uint32
acceptor_wait_for_dcestyle(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)
{
    OM_uint32 ret;
    krb5_error_code kret;
    krb5_data inbuf;
    int32_t r_seq_number, l_seq_number;

    /*
     * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP
     */

    inbuf.length = input_token_buffer->length;
    inbuf.data = input_token_buffer->value;

    /*
     * We need to remeber the old remote seq_number, then check if the
     * client has replied with our local seq_number, and then reset
     * the remote seq_number to the old value
     */
    {
	kret = krb5_auth_con_getlocalseqnumber(context,
					       ctx->auth_context,
					       &l_seq_number);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	kret = krb5_auth_con_getremoteseqnumber(context,
						ctx->auth_context,
						&r_seq_number);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	kret = krb5_auth_con_setremoteseqnumber(context,
						ctx->auth_context,
						l_seq_number);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}
    }

    /*
     * We need to verify the AP_REP, but we need to flag that this is
     * DCE_STYLE, so don't check the timestamps this time, but put the
     * flag DO_TIME back afterward.
    */
    {
	krb5_ap_rep_enc_part *repl;
	int32_t auth_flags;

	krb5_auth_con_removeflags(context,
				  ctx->auth_context,
				  KRB5_AUTH_CONTEXT_DO_TIME,
				  &auth_flags);

	kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}
	krb5_free_ap_rep_enc_part(context, repl);
	krb5_auth_con_setflags(context, ctx->auth_context, auth_flags);
    }

    /* We need to check the liftime */
    {
	OM_uint32 lifetime_rec;

	ret = _gsskrb5_lifetime_left(minor_status,
				     context,
				     ctx->lifetime,
				     &lifetime_rec);
	if (ret) {
	    return ret;
	}
	if (lifetime_rec == 0) {
	    return GSS_S_CONTEXT_EXPIRED;
	}

	if (time_rec) *time_rec = lifetime_rec;
    }

    /* We need to give the caller the flags which are in use */
    if (ret_flags) *ret_flags = ctx->flags;

    if (src_name) {
	kret = krb5_copy_principal(context,
				   ctx->source,
				   (gsskrb5_name*)src_name);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}
    }

    /*
     * After the krb5_rd_rep() the remote and local seq_number should
     * be the same, because the client just replies the seq_number
     * from our AP-REP in its AP-REP, but then the client uses the
     * seq_number from its AP-REQ for GSS_wrap()
     */
    {
	int32_t tmp_r_seq_number, tmp_l_seq_number;

	kret = krb5_auth_con_getremoteseqnumber(context,
						ctx->auth_context,
						&tmp_r_seq_number);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	kret = krb5_auth_con_getlocalseqnumber(context,
					       ctx->auth_context,
					       &tmp_l_seq_number);
	if (kret) {

	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	/*
	 * Here we check if the client has responsed with our local seq_number,
	 */
	if (tmp_r_seq_number != tmp_l_seq_number) {
	    return GSS_S_UNSEQ_TOKEN;
	}
    }

    /*
     * We need to reset the remote seq_number, because the client will use,
     * the old one for the GSS_wrap() calls
     */
    {
	kret = krb5_auth_con_setremoteseqnumber(context,
						ctx->auth_context,
						r_seq_number);
	if (kret) {
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}
    }

    return gsskrb5_acceptor_ready(minor_status, ctx, context,
				  delegated_cred_handle);
}
static OM_uint32
export_lucid_sec_context_v1(OM_uint32 *minor_status,
			    gsskrb5_ctx context_handle,
			    krb5_context context,
			    gss_buffer_set_t *data_set)
{
    krb5_storage *sp = NULL;
    OM_uint32 major_status = GSS_S_COMPLETE;
    krb5_error_code ret;
    krb5_keyblock *key = NULL;
    int32_t number;
    int is_cfx;
    krb5_data data;

    *minor_status = 0;

    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);

    is_cfx = (context_handle->more_flags & IS_CFX);

    sp = krb5_storage_emem();
    if (sp == NULL) {
	_gsskrb5_clear_status();
	ret = ENOMEM;
	goto out;
    }

    ret = krb5_store_int32(sp, 1);
    if (ret) goto out;
    ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0);
    if (ret) goto out;
    /* XXX need krb5_store_int64() */
    ret = krb5_store_int32(sp, context_handle->endtime);
    if (ret) goto out;
    krb5_auth_con_getlocalseqnumber (context,
				     context_handle->auth_context,
				     &number);
    ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
    if (ret) goto out;
    ret = krb5_store_uint32(sp, (uint32_t)number);
    if (ret) goto out;
    krb5_auth_con_getremoteseqnumber (context,
				      context_handle->auth_context,
				      &number);
    ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */
    if (ret) goto out;
    ret = krb5_store_uint32(sp, (uint32_t)number);
    if (ret) goto out;
    ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0);
    if (ret) goto out;

    ret = _gsskrb5i_get_token_key(context_handle, context, &key);
    if (ret) goto out;

    if (is_cfx == 0) {
	int sign_alg, seal_alg;

	switch (key->keytype) {
	case ETYPE_DES_CBC_CRC:
	case ETYPE_DES_CBC_MD4:
	case ETYPE_DES_CBC_MD5:
	    sign_alg = 0;
	    seal_alg = 0;
	    break;
	case ETYPE_DES3_CBC_MD5:
	case ETYPE_DES3_CBC_SHA1:
	    sign_alg = 4;
	    seal_alg = 2;
	    break;
	case ETYPE_ARCFOUR_HMAC_MD5:
	case ETYPE_ARCFOUR_HMAC_MD5_56:
	    sign_alg = 17;
	    seal_alg = 16;
	    break;
	default:
	    sign_alg = -1;
	    seal_alg = -1;
	    break;
	}
	ret = krb5_store_int32(sp, sign_alg);
	if (ret) goto out;
	ret = krb5_store_int32(sp, seal_alg);
	if (ret) goto out;
	/* ctx_key */
	ret = krb5_store_keyblock(sp, *key);
	if (ret) goto out;
    } else {
	int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0;

	/* have_acceptor_subkey */
	ret = krb5_store_int32(sp, subkey_p);
	if (ret) goto out;
	/* ctx_key */
	ret = krb5_store_keyblock(sp, *key);
	if (ret) goto out;
	/* acceptor_subkey */
	if (subkey_p) {
	    ret = krb5_store_keyblock(sp, *key);
	    if (ret) goto out;
	}
    }
    ret = krb5_storage_to_data(sp, &data);
    if (ret) goto out;

    {
	gss_buffer_desc ad_data;

	ad_data.value = data.data;
	ad_data.length = data.length;

	ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set);
	krb5_data_free(&data);
	if (ret)
	    goto out;
    }

out:
    if (key)
	krb5_free_keyblock (context, key);
    if (sp)
	krb5_storage_free(sp);
    if (ret) {
	*minor_status = ret;
	major_status = GSS_S_FAILURE;
    }
    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
    return major_status;
}