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; }
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; }
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; }
"\x6a\x81\xb8\x30\x81\xb5\xa1\x03\x02\x01\x05\xa2\x03\x02\x01\x0a" "\xa4\x81\xa8\x30\x81\xa5\xa0\x07\x03\x05\x00\x40\x01\x00\x00\xa1" "\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b\x03\x6c\x68" "\x61\xa2\x24\x1b\x22\x57\x45\x4c\x4c\x4b\x4e\x4f\x57\x4e\x3a\x43" "\x4f\x4d\x2e\x41\x50\x50\x4c\x45\x2e\x4c\x4b\x44\x43\x3a\x6c\x6f" "\x63\x61\x6c\x68\x6f\x73\x74\xa3\x37\x30\x35\xa0\x03\x02\x01\x01" "\xa1\x2e\x30\x2c\x1b\x06\x6b\x72\x62\x74\x67\x74\x1b\x22\x57\x45" "\x4c\x4c\x4b\x4e\x4f\x57\x4e\x3a\x43\x4f\x4d\x2e\x41\x50\x50\x4c" "\x45\x2e\x4c\x4b\x44\x43\x3a\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74" "\xa5\x11\x18\x0f\x32\x30\x31\x30\x30\x37\x33\x30\x31\x30\x33\x35" "\x31\x38\x5a\xa7\x06\x02\x04\x3a\xcc\xb8\xba\xa8\x0e\x30\x0c\x02" "\x01\x12\x02\x01\x11\x02\x01\x10\x02\x01\x17", .length = 187 }, recv = { .data = NULL, .length = 0 }; ret = krb5_sendto_ctx_alloc(context, &ctx); if (ret) krb5_err(context, 1, ret, "krb5_sendto_ctx_alloc"); if (use_large_flag) krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG); ret = krb5_sendto_context(context, ctx, &send, realm_string, &recv); if (ret) krb5_err(context, 1, ret, "krb5_sendto_context"); krb5_sendto_ctx_free(context, ctx); krb5_free_context(context); return 0;
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_sendto_context(krb5_context context, krb5_sendto_ctx ctx, const krb5_data *send_data, const krb5_realm realm, krb5_data *receive) { krb5_error_code ret; krb5_krbhst_handle handle = NULL; int type, freectx = 0; int action; krb5_data_zero(receive); if (ctx == NULL) { freectx = 1; ret = krb5_sendto_ctx_alloc(context, &ctx); if (ret) return ret; } type = ctx->type; if (type == 0) { if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) type = KRB5_KRBHST_ADMIN; else type = KRB5_KRBHST_KDC; } if ((int)send_data->length > context->large_msg_size) ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; /* loop until we get back a appropriate response */ do { action = KRB5_SENDTO_DONE; krb5_data_free(receive); if (handle == NULL) { ret = krb5_krbhst_init_flags(context, realm, type, ctx->flags, &handle); if (ret) { if (freectx) krb5_sendto_ctx_free(context, ctx); return ret; } } ret = krb5_sendto(context, send_data, handle, receive); if (ret) break; if (ctx->func) { ret = (*ctx->func)(context, ctx, ctx->data, receive, &action); if (ret) break; } if (action != KRB5_SENDTO_CONTINUE) { krb5_krbhst_free(context, handle); handle = NULL; } } while (action != KRB5_SENDTO_DONE); if (handle) krb5_krbhst_free(context, handle); if (ret == KRB5_KDC_UNREACH) krb5_set_error_message(context, ret, N_("unable to reach any KDC in realm %s", ""), realm); if (ret) krb5_data_free(receive); if (freectx) krb5_sendto_ctx_free(context, ctx); return ret; }
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; }