Beispiel #1
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sendto_kdc_flags(krb5_context context,
		      const krb5_data *send_data,
		      const krb5_realm *realm,
		      krb5_data *receive,
		      int flags)
{
    krb5_error_code ret;
    krb5_sendto_ctx ctx;

    ret = krb5_sendto_ctx_alloc(context, &ctx);
    if (ret)
	return ret;
    krb5_sendto_ctx_add_flags(ctx, flags);
    krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL);

    ret = krb5_sendto_context(context, ctx, send_data, *realm, receive);
    krb5_sendto_ctx_free(context, ctx);
    return ret;
}
Beispiel #2
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
{
    krb5_sendto_ctx stctx = NULL;
    krb5_krbhst_info *hostinfo = NULL;
    krb5_error_code ret;
    krb5_data in, out;
    unsigned int flags = 0;

    krb5_data_zero(&in);
    krb5_data_zero(&out);

    ret = krb5_sendto_ctx_alloc(context, &stctx);
    if (ret)
	goto out;
    krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);

    while (1) {
	flags = 0;
	ret = krb5_init_creds_step(context, ctx, &in, &out, hostinfo, &flags);
	krb5_data_free(&in);
	if (ret)
	    goto out;

	if ((flags & 1) == 0)
	    break;

	ret = krb5_sendto_context (context, stctx, &out, 
				   ctx->cred.client->realm, &in);
    	if (ret)
	    goto out;

    }

 out:
    if (stctx)
	krb5_sendto_ctx_free(context, stctx);

    return ret;
}
Beispiel #3
0
static krb5_error_code
get_cred_kdc(krb5_context context,
	     krb5_ccache id,
	     krb5_kdc_flags flags,
	     krb5_addresses *addresses,
	     krb5_creds *in_creds,
	     krb5_creds *krbtgt,
	     krb5_principal impersonate_principal,
	     Ticket *second_ticket,
	     krb5_creds *out_creds)
{
    TGS_REQ req;
    krb5_data enc;
    krb5_data resp;
    krb5_kdc_rep rep;
    KRB_ERROR error;
    krb5_error_code ret;
    unsigned nonce;
    krb5_keyblock *subkey = NULL;
    size_t len;
    Ticket second_ticket_data;
    METHOD_DATA padata;

    krb5_data_zero(&resp);
    krb5_data_zero(&enc);
    padata.val = NULL;
    padata.len = 0;

    krb5_generate_random_block(&nonce, sizeof(nonce));
    nonce &= 0xffffffff;

    if(flags.b.enc_tkt_in_skey && second_ticket == NULL){
	ret = decode_Ticket(in_creds->second_ticket.data,
			    in_creds->second_ticket.length,
			    &second_ticket_data, &len);
	if(ret)
	    return ret;
	second_ticket = &second_ticket_data;
    }


    if (impersonate_principal) {
	krb5_crypto crypto;
	PA_S4U2Self self;
	krb5_data data;
	void *buf;
	size_t size;

	self.name = impersonate_principal->name;
	self.realm = impersonate_principal->realm;
	self.auth = estrdup("Kerberos");
	
	ret = _krb5_s4u2self_to_checksumdata(context, &self, &data);
	if (ret) {
	    free(self.auth);
	    goto out;
	}

	ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto);
	if (ret) {
	    free(self.auth);
	    krb5_data_free(&data);
	    goto out;
	}

	ret = krb5_create_checksum(context,
				   crypto,
				   KRB5_KU_OTHER_CKSUM,
				   0,
				   data.data,
				   data.length,
				   &self.cksum);
	krb5_crypto_destroy(context, crypto);
	krb5_data_free(&data);
	if (ret) {
	    free(self.auth);
	    goto out;
	}

	ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret);
	free(self.auth);
	free_Checksum(&self.cksum);
	if (ret)
	    goto out;
	if (len != size)
	    krb5_abortx(context, "internal asn1 error");
	
	ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len);
	if (ret)
	    goto out;
    }

    ret = init_tgs_req (context,
			id,
			addresses,
			flags,
			second_ticket,
			in_creds,
			krbtgt,
			nonce,
			&padata,
			&subkey,
			&req);
    if (ret)
	goto out;

    ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret);
    if (ret)
	goto out;
    if(enc.length != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    /* don't free addresses */
    req.req_body.addresses = NULL;
    free_TGS_REQ(&req);

    /*
     * Send and receive
     */
    {
	krb5_sendto_ctx stctx;
	ret = krb5_sendto_ctx_alloc(context, &stctx);
	if (ret)
	    return ret;
	krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);

	ret = krb5_sendto_context (context, stctx, &enc,
				   krbtgt->server->name.name_string.val[1],
				   &resp);
	krb5_sendto_ctx_free(context, stctx);
    }
    if(ret)
	goto out;

    memset(&rep, 0, sizeof(rep));
    if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0) {
	unsigned eflags = 0;

	ret = krb5_copy_principal(context,
				  in_creds->client,
				  &out_creds->client);
	if(ret)
	    goto out2;
	ret = krb5_copy_principal(context,
				  in_creds->server,
				  &out_creds->server);
	if(ret)
	    goto out2;
	/* this should go someplace else */
	out_creds->times.endtime = in_creds->times.endtime;

	/* XXX should do better testing */
	if (flags.b.constrained_delegation || impersonate_principal)
	    eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;

	ret = _krb5_extract_ticket(context,
				   &rep,
				   out_creds,
				   &krbtgt->session,
				   NULL,
				   0,
				   &krbtgt->addresses,
				   nonce,
				   eflags,
				   decrypt_tkt_with_subkey,
				   subkey);
    out2:
	krb5_free_kdc_rep(context, &rep);
    } else if(krb5_rd_error(context, &resp, &error) == 0) {
	ret = krb5_error_from_rd_error(context, &error, in_creds);
	krb5_free_error_contents(context, &error);
    } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) {
	ret = KRB5KRB_AP_ERR_V4_REPLY;
	krb5_clear_error_message(context);
    } else {
	ret = KRB5KRB_AP_ERR_MSG_TYPE;
	krb5_clear_error_message(context);
    }

out:
    if (second_ticket == &second_ticket_data)
	free_Ticket(&second_ticket_data);
    free_METHOD_DATA(&padata);
    krb5_data_free(&resp);
    krb5_data_free(&enc);
    if(subkey)
	krb5_free_keyblock(context, subkey);
    return ret;

}
Beispiel #4
0
static krb5_error_code
change_password_loop(krb5_context	context,
                     struct request *request,
                     int		*result_code,
                     krb5_data		*result_code_string,
                     krb5_data		*result_string,
                     struct kpwd_proc	*proc)
{
    krb5_error_code ret;
    krb5_data zero, zero2;
    krb5_sendto_ctx ctx = NULL;
    krb5_realm realm;

    krb5_data_zero(&zero);
    krb5_data_zero(&zero2);

    if (request->target)
        realm = request->target->realm;
    else
        realm = request->creds->client->realm;

    _krb5_debugx(context, 1, "trying to set password using: %s in realm %s",
                 proc->name, realm);

    ret = krb5_auth_con_init(context, &request->ac);
    if (ret)
        goto out;

    krb5_auth_con_setflags(context, request->ac, KRB5_AUTH_CONTEXT_DO_SEQUENCE);

    ret = krb5_sendto_ctx_alloc(context, &ctx);
    if (ret)
        goto out;

    krb5_sendto_ctx_set_type(ctx, KRB5_KRBHST_CHANGEPW);

    /* XXX this is a evil hack */
    if (request->creds->ticket.length > 700) {
        _krb5_debugx(context, 1, "using TCP since the ticket is large: %lu",
                     (unsigned long)request->creds->ticket.length);
        krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG);
    }

    _krb5_sendto_ctx_set_prexmit(ctx, proc->prexmit, request);

    ret = krb5_sendto_context(context, ctx, &zero, realm, &zero2);

    if (ret == 0)
        ret = proc->process_rep(context, request->ac, &zero2,
                                result_code, result_code_string, result_string);

out:
    _krb5_debugx(context, 1, "set password using %s returned: %d result_code %d",
                 proc->name, ret, *result_code);

    krb5_auth_con_free(context, request->ac);
    if (ctx)
        krb5_sendto_ctx_free(context, ctx);

    krb5_data_free(&zero2);

    if (ret == KRB5_KDC_UNREACH) {
        krb5_set_error_message(context,
                               ret,
                               N_("Unable to reach any changepw server "
                                  " in realm %s", "realm"), realm);
        *result_code = KRB5_KPASSWD_HARDERROR;
    }
    return ret;
}