示例#1
0
static krb5_error_code
prepare_error_as (struct kdc_request_state *rstate, krb5_kdc_req *request,
                  int error, krb5_pa_data **e_data, krb5_boolean typed_e_data,
                  krb5_principal canon_client, krb5_data **response,
                  const char *status)
{
    krb5_error errpkt;
    krb5_error_code retval;
    krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
    kdc_realm_t *kdc_active_realm = rstate->realm_data;

    errpkt.ctime = request->nonce;
    errpkt.cusec = 0;

    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
    if (retval)
        return retval;
    errpkt.error = error;
    errpkt.server = request->server;
    errpkt.client = (error == KRB5KDC_ERR_WRONG_REALM) ? canon_client :
        request->client;
    errpkt.text = string2data((char *)status);

    if (e_data != NULL) {
        if (typed_e_data)
            retval = encode_krb5_typed_data(e_data, &e_data_asn1);
        else
            retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
        if (retval)
            goto cleanup;
        errpkt.e_data = *e_data_asn1;
    } else
        errpkt.e_data = empty_data();

    retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
                                   &errpkt, &fast_edata);
    if (retval)
        goto cleanup;
    if (fast_edata != NULL)
        errpkt.e_data = *fast_edata;

    scratch = k5alloc(sizeof(*scratch), &retval);
    if (scratch == NULL)
        goto cleanup;
    if (kdc_fast_hide_client(rstate) && errpkt.client != NULL)
        errpkt.client = (krb5_principal)krb5_anonymous_principal();
    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
    if (retval)
        goto cleanup;

    *response = scratch;
    scratch = NULL;

cleanup:
    krb5_free_data(kdc_context, fast_edata);
    krb5_free_data(kdc_context, e_data_asn1);
    free(scratch);
    return retval;
}
示例#2
0
/* this function allocates 'data' using malloc.
 * The caller is responsible for freeing it */
static void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data)
{
	krb5_error_code ret = 0;
	krb5_pa_data pa, *ppa = NULL;
	krb5_data *d = NULL;

	if (!e_data)
		return;

	e_data->data   = NULL;
	e_data->length = 0;

	pa.magic		= KV5M_PA_DATA;
	pa.pa_type		= KRB5_PADATA_PW_SALT;
	pa.length		= 12;
	pa.contents		= malloc(pa.length);
	if (!pa.contents) {
		return;
	}

	SIVAL(pa.contents, 0, NT_STATUS_V(nt_status));
	SIVAL(pa.contents, 4, 0);
	SIVAL(pa.contents, 8, 1);

	ppa = &pa;

	ret = encode_krb5_padata_sequence(&ppa, &d);
	free(pa.contents);
	if (ret) {
		return;
	}

	e_data->data   = (uint8_t *)d->data;
	e_data->length = d->length;

	/* free d, not d->data - gd */
	free(d);

	return;
}
示例#3
0
文件: do_tgs_req.c 项目: jmoldow/krb5
static krb5_error_code
prepare_error_tgs (struct kdc_request_state *state,
                   krb5_kdc_req *request, krb5_ticket *ticket, int error,
                   krb5_principal canon_server,
                   krb5_data **response, const char *status,
                   krb5_pa_data **e_data)
{
    krb5_error errpkt;
    krb5_error_code retval = 0;
    krb5_data *scratch, *e_data_asn1 = NULL, *fast_edata = NULL;

    errpkt.ctime = request->nonce;
    errpkt.cusec = 0;

    if ((retval = krb5_us_timeofday(kdc_context, &errpkt.stime,
                                    &errpkt.susec)))
        return(retval);
    errpkt.error = error;
    errpkt.server = request->server;
    if (ticket && ticket->enc_part2)
        errpkt.client = ticket->enc_part2->client;
    else
        errpkt.client = NULL;
    errpkt.text.length = strlen(status);
    if (!(errpkt.text.data = strdup(status)))
        return ENOMEM;

    if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) {
        free(errpkt.text.data);
        return ENOMEM;
    }

    if (e_data != NULL) {
        retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
        if (retval) {
            free(scratch);
            free(errpkt.text.data);
            return retval;
        }
        errpkt.e_data = *e_data_asn1;
    } else
        errpkt.e_data = empty_data();

    if (state) {
        retval = kdc_fast_handle_error(kdc_context, state, request, e_data,
                                       &errpkt, &fast_edata);
    }
    if (retval) {
        free(scratch);
        free(errpkt.text.data);
        krb5_free_data(kdc_context, e_data_asn1);
        return retval;
    }
    if (fast_edata)
        errpkt.e_data = *fast_edata;
    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
    free(errpkt.text.data);
    krb5_free_data(kdc_context, e_data_asn1);
    krb5_free_data(kdc_context, fast_edata);
    if (retval)
        free(scratch);
    else
        *response = scratch;

    return retval;
}
示例#4
0
static void
kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
                   krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
                   krb5_pa_data *pa_data, krb5_kdcpreauth_callbacks cb,
                   krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                   krb5_kdcpreauth_verify_respond_fn respond, void *arg)
{
    krb5_error_code retval, saved_retval = 0;
    krb5_sam_response_2 *sr2 = NULL;
    krb5_data scratch, *scratch2, *e_data = NULL;
    char *client_name = NULL;
    krb5_sam_challenge_2 *out_sc2 = NULL;
    krb5_db_entry *client = cb->client_entry(context, rock);

    scratch.data = (char *) pa_data->contents;
    scratch.length = pa_data->length;

    retval = krb5_unparse_name(context, client->princ, &client_name);
    if (retval)
        goto cleanup;

    retval = decode_krb5_sam_response_2(&scratch, &sr2);
    if (retval) {
        com_err("krb5kdc",  retval,
                "while decoding SAM_RESPONSE_2 in verify_sam_response_2");
        sr2 = NULL;
        goto cleanup;
    }

    switch (sr2->sam_type) {
#ifdef ARL_SECURID_PREAUTH
    case PA_SAM_TYPE_SECURID:
        retval = verify_securid_data_2(context, client, sr2, enc_tkt_reply,
                                       pa_data, &out_sc2);
        if (retval)
            goto cleanup;
        break;
#endif  /* ARL_SECURID_PREAUTH */
#ifdef GRAIL_PREAUTH
    case PA_SAM_TYPE_GRAIL:
        retval = verify_grail_data(context, client, sr2, enc_tkt_reply,
                                   pa_data, &out_sc2);
        if (retval)
            goto cleanup;
        break;
#endif /* GRAIL_PREAUTH */
    default:
        retval = KRB5_PREAUTH_BAD_TYPE;
        com_err("krb5kdc", retval, "while verifying SAM 2 data");
        break;
    }

    /*
     * It is up to the method-specific verify routine to set the
     * ticket flags to indicate TKT_FLG_HW_AUTH and/or
     * TKT_FLG_PRE_AUTH.  Some methods may require more than one round
     * of dialog with the client and must return successfully from
     * their verify routine.  If does not set the TGT flags, the
     * required_preauth conditions will not be met and it will try
     * again to get enough preauth data from the client.  Do not set
     * TGT flags here.
     */
cleanup:
    /*
     * Note that e_data is an output even in error conditions.  If we
     * successfully encode the output e_data, we return whatever error is
     * received above.  Otherwise we return the encoding error.
     */
    saved_retval = retval;
    if (out_sc2) {
        krb5_pa_data pa_out;
        krb5_pa_data *pa_array[2];
        pa_array[0] = &pa_out;
        pa_array[1] = NULL;
        pa_out.pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
        retval = encode_krb5_sam_challenge_2(out_sc2, &scratch2);
        krb5_free_sam_challenge_2(context, out_sc2);
        if (retval)
            goto encode_error;
        pa_out.contents = (krb5_octet *) scratch2->data;
        pa_out.length = scratch2->length;
        retval = encode_krb5_padata_sequence(pa_array, &e_data);
        krb5_free_data(context, scratch2);
    }
encode_error:
    krb5_free_sam_response_2(context, sr2);
    free(client_name);
    if (retval == 0)
        retval = saved_retval;

    (*respond)(arg, retval, NULL, NULL, NULL);
}
示例#5
0
文件: fast_util.c 项目: hautreux/krb5
/*
 * We assume the caller is responsible for passing us an in_padata
 * sufficient to include in a FAST error.  In the FAST case we will
 * set *fast_edata_out to the edata to be included in the error; in
 * the non-FAST case we will set it to NULL.
 */
krb5_error_code
kdc_fast_handle_error(krb5_context context,
                      struct kdc_request_state *state,
                      krb5_kdc_req *request,
                      krb5_pa_data  **in_padata, krb5_error *err,
                      krb5_data **fast_edata_out)
{
    krb5_error_code retval = 0;
    krb5_fast_response resp;
    krb5_error fx_error;
    krb5_data *encoded_fx_error = NULL, *encrypted_reply = NULL;
    krb5_pa_data pa[1];
    krb5_pa_data *outer_pa[3], *cookie = NULL;
    krb5_pa_data **inner_pa = NULL;
    size_t size = 0;
    kdc_realm_t *kdc_active_realm = state->realm_data;

    *fast_edata_out = NULL;
    memset(outer_pa, 0, sizeof(outer_pa));
    if (state->armor_key == NULL)
        return 0;
    fx_error = *err;
    fx_error.e_data.data = NULL;
    fx_error.e_data.length = 0;
    for (size = 0; in_padata&&in_padata[size]; size++);
    size +=3;
    inner_pa = calloc(size, sizeof(krb5_pa_data *));
    if (inner_pa == NULL)
        retval = ENOMEM;
    if (retval == 0)
        for (size=0; in_padata&&in_padata[size]; size++)
            inner_pa[size] = in_padata[size];
    if (retval == 0)
        retval = encode_krb5_error(&fx_error, &encoded_fx_error);
    if (retval == 0) {
        pa[0].pa_type = KRB5_PADATA_FX_ERROR;
        pa[0].length = encoded_fx_error->length;
        pa[0].contents = (unsigned char *) encoded_fx_error->data;
        inner_pa[size++] = &pa[0];
        if (krb5int_find_pa_data(kdc_context,
                                 inner_pa, KRB5_PADATA_FX_COOKIE) == NULL)
            retval = kdc_preauth_get_cookie(state, &cookie);
    }
    if (cookie != NULL)
        inner_pa[size++] = cookie;
    if (retval == 0) {
        resp.padata = inner_pa;
        resp.nonce = request->nonce;
        resp.strengthen_key = NULL;
        resp.finished = NULL;
    }
    if (retval == 0)
        retval = encrypt_fast_reply(state, &resp, &encrypted_reply);
    if (inner_pa)
        free(inner_pa); /*contained storage from caller and our stack*/
    if (cookie) {
        free(cookie->contents);
        free(cookie);
        cookie = NULL;
    }
    if (retval == 0) {
        pa[0].pa_type = KRB5_PADATA_FX_FAST;
        pa[0].length = encrypted_reply->length;
        pa[0].contents = (unsigned char *) encrypted_reply->data;
        outer_pa[0] = &pa[0];
    }
    retval = encode_krb5_padata_sequence(outer_pa, fast_edata_out);
    if (encrypted_reply)
        krb5_free_data(kdc_context, encrypted_reply);
    if (encoded_fx_error)
        krb5_free_data(kdc_context, encoded_fx_error);
    return retval;
}
示例#6
0
static krb5_error_code
prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request,
                 krb5_db_entry *local_tgt, int error, krb5_pa_data **e_data_in,
                 krb5_boolean typed_e_data, krb5_principal canon_client,
                 krb5_data **response, const char *status)
{
    krb5_error errpkt;
    krb5_error_code retval;
    krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL;
    krb5_pa_data **e_data = NULL, *cookie = NULL;
    kdc_realm_t *kdc_active_realm = rstate->realm_data;
    size_t count;

    if (e_data_in != NULL) {
        /* Add a PA-FX-COOKIE to e_data_in.  e_data is a shallow copy
         * containing aliases. */
        for (count = 0; e_data_in[count] != NULL; count++);
        e_data = calloc(count + 2, sizeof(*e_data));
        if (e_data == NULL)
            return ENOMEM;
        memcpy(e_data, e_data_in, count * sizeof(*e_data));
        retval = kdc_fast_make_cookie(kdc_context, rstate, local_tgt,
                                      request->client, &cookie);
        e_data[count] = cookie;
    }

    errpkt.ctime = request->nonce;
    errpkt.cusec = 0;

    retval = krb5_us_timeofday(kdc_context, &errpkt.stime, &errpkt.susec);
    if (retval)
        goto cleanup;
    errpkt.error = error;
    errpkt.server = request->server;
    errpkt.client = (error == KDC_ERR_WRONG_REALM) ? canon_client :
                    request->client;
    errpkt.text = string2data((char *)status);

    if (e_data != NULL) {
        if (typed_e_data)
            retval = encode_krb5_typed_data(e_data, &e_data_asn1);
        else
            retval = encode_krb5_padata_sequence(e_data, &e_data_asn1);
        if (retval)
            goto cleanup;
        errpkt.e_data = *e_data_asn1;
    } else
        errpkt.e_data = empty_data();

    retval = kdc_fast_handle_error(kdc_context, rstate, request, e_data,
                                   &errpkt, &fast_edata);
    if (retval)
        goto cleanup;
    if (fast_edata != NULL)
        errpkt.e_data = *fast_edata;

    scratch = k5alloc(sizeof(*scratch), &retval);
    if (scratch == NULL)
        goto cleanup;
    if (kdc_fast_hide_client(rstate) && errpkt.client != NULL)
        errpkt.client = (krb5_principal)krb5_anonymous_principal();
    retval = krb5_mk_error(kdc_context, &errpkt, scratch);
    if (retval)
        goto cleanup;

    *response = scratch;
    scratch = NULL;

cleanup:
    krb5_free_data(kdc_context, fast_edata);
    krb5_free_data(kdc_context, e_data_asn1);
    free(scratch);
    free(e_data);
    if (cookie != NULL)
        free(cookie->contents);
    free(cookie);
    return retval;
}