krb5_error_code KRB5_CALLCONV krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata) { krb5_error_code retval; krb5_keyblock * keyblock; krb5_replay_data replaydata; /* Get keyblock */ if ((keyblock = auth_context->recv_subkey) == NULL) keyblock = auth_context->keyblock; if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) /* Need a better error */ return KRB5_RC_REQUIRED; if (!auth_context->remote_addr) return KRB5_REMOTE_ADDR_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; { krb5_address * premote_fulladdr; krb5_address * plocal_fulladdr = NULL; krb5_address remote_fulladdr; krb5_address local_fulladdr; CLEANUP_INIT(2); if (auth_context->local_addr) { if (auth_context->local_port) { if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, auth_context->local_port, &local_fulladdr))){ CLEANUP_PUSH(local_fulladdr.contents, free); plocal_fulladdr = &local_fulladdr; } else { return retval; } } else { plocal_fulladdr = auth_context->local_addr; } } if (auth_context->remote_port) { if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, auth_context->remote_port, &remote_fulladdr))){ CLEANUP_PUSH(remote_fulladdr.contents, free); premote_fulladdr = &remote_fulladdr; } else { CLEANUP_DONE(); return retval; } } else { premote_fulladdr = auth_context->remote_addr; } memset(&replaydata, 0, sizeof(replaydata)); if ((retval = krb5_rd_priv_basic(context, inbuf, keyblock, plocal_fulladdr, premote_fulladdr, auth_context->i_vector, &replaydata, outbuf))) { CLEANUP_DONE(); return retval; } CLEANUP_DONE(); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5int_check_clockskew(context, replaydata.timestamp))) goto error; if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, "_priv", &replay.client))) goto error; replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { free(replay.client); goto error; } free(replay.client); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { if (!krb5int_auth_con_chkseqnum(context, auth_context, replaydata.seq)) { retval = KRB5KRB_AP_ERR_BADORDER; goto error; } auth_context->remote_seq_number++; } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; outdata->seq = replaydata.seq; } /* everything is ok - return data to the user */ return 0; error:; free(outbuf->data); outbuf->length = 0; outbuf->data = NULL; return retval; }
krb5_error_code KRB5_CALLCONV krb5_mk_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata) { krb5_error_code retval; krb5_key key; krb5_replay_data replaydata; krb5_data buf = empty_data(); *outbuf = empty_data(); /* Clear replaydata block */ memset(&replaydata, 0, sizeof(krb5_replay_data)); /* Get keyblock */ if ((key = auth_context->send_subkey) == NULL) key = auth_context->key; /* Get replay info */ if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) /* Need a better error */ return KRB5_RC_REQUIRED; if (!auth_context->local_addr) return KRB5_LOCAL_ADDR_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) { if ((retval = krb5_us_timeofday(context, &replaydata.timestamp, &replaydata.usec))) return retval; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; } } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { replaydata.seq = auth_context->local_seq_number++; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) outdata->seq = replaydata.seq; } { krb5_address * premote_fulladdr = NULL; krb5_address * plocal_fulladdr; krb5_address remote_fulladdr; krb5_address local_fulladdr; CLEANUP_INIT(2); if (auth_context->local_port) { if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, auth_context->local_port, &local_fulladdr))) { CLEANUP_PUSH(local_fulladdr.contents, free); plocal_fulladdr = &local_fulladdr; } else { goto error; } } else { plocal_fulladdr = auth_context->local_addr; } if (auth_context->remote_addr) { if (auth_context->remote_port) { if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, auth_context->remote_port, &remote_fulladdr))){ CLEANUP_PUSH(remote_fulladdr.contents, free); premote_fulladdr = &remote_fulladdr; } else { CLEANUP_DONE(); goto error; } } else { premote_fulladdr = auth_context->remote_addr; } } if ((retval = mk_priv_basic(context, userdata, key, &replaydata, plocal_fulladdr, premote_fulladdr, &auth_context->cstate, &buf))) { CLEANUP_DONE(); goto error; } CLEANUP_DONE(); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5_gen_replay_name(context, auth_context->local_addr, "_priv", &replay.client))) goto error; replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { /* should we really error out here? XXX */ free(replay.client); goto error; } free(replay.client); } *outbuf = buf; return 0; error: krb5_free_data_contents(context, &buf); if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) auth_context->local_seq_number--; return retval; }
/* XXX - check for cleanup */ krb5_error_code setup_auth_context(krb5_context context, krb5_auth_context auth_context, struct sockaddr_in *localaddr, struct sockaddr_in *remoteaddr, char *uniq) { krb5_address laddr, raddr, *portlocal_addr; krb5_rcache rcache; krb5_data rcache_name; char *outaddr; krb5_error_code retval; #ifndef HEIMDAL /* Setting ports isn't compatible with Heimdal, if this code is enabled, it's not possible to have an interoperable setup */ #if 0 laddr.addrtype = ADDRTYPE_IPPORT; laddr.length = sizeof(localaddr->sin_port); laddr.contents = (krb5_octet *)&(localaddr->sin_port); raddr.addrtype = ADDRTYPE_IPPORT; raddr.length = sizeof(remoteaddr->sin_port); raddr.contents = (krb5_octet *)&(remoteaddr->sin_port); if (retval = krb5_auth_con_setports(context, auth_context, &laddr, &raddr)) { sprintf(auth_con_error, "%s while setting auth_con ports\n", error_message(retval)); return retval; } #endif #endif #ifdef HEIMDAL laddr.addr_type = KRB5_ADDRESS_INET; laddr.address.length = sizeof(localaddr->sin_addr); laddr.address.data = (void *)&(localaddr->sin_addr); raddr.addr_type = KRB5_ADDRESS_INET; raddr.address.length = sizeof(remoteaddr->sin_addr); raddr.address.data = (void *)&(remoteaddr->sin_addr); #else laddr.addrtype = ADDRTYPE_INET; laddr.length = sizeof(localaddr->sin_addr); laddr.contents = (krb5_octet *)&(localaddr->sin_addr); raddr.addrtype = ADDRTYPE_INET; raddr.length = sizeof(remoteaddr->sin_addr); raddr.contents = (krb5_octet *)&(remoteaddr->sin_addr); #endif if (retval = krb5_auth_con_setaddrs(context, auth_context, &laddr, &raddr)) { sprintf(auth_con_error, "%s while setting auth_con addresses\n", error_message(retval)); return retval; } #ifdef HEIMDAL #else /* Set up replay cache */ if ((retval = krb5_gen_portaddr(context, &laddr, (krb5_pointer) &(localaddr->sin_port), &portlocal_addr))) { sprintf(auth_con_error, "%s while generating port address", error_message(retval)); return retval; } if ((retval = krb5_gen_replay_name(context, portlocal_addr, uniq, &outaddr))) { sprintf(auth_con_error, "%s while generating replay cache name", error_message(retval)); return retval; } rcache_name.length = strlen(outaddr); rcache_name.data = outaddr; if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) { sprintf(auth_con_error, "%s while getting server rcache", error_message(retval)); return retval; } if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) { sprintf(auth_con_error, "%s setting rcache", error_message(retval)); return retval; } #endif return retval; }
krb5_error_code KRB5_CALLCONV krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata) { krb5_error_code retval; krb5_key key; krb5_replay_data replaydata; /* Clear replaydata block */ memset(&replaydata, 0, sizeof(krb5_replay_data)); /* Get key */ if ((key = auth_context->send_subkey) == NULL) key = auth_context->key; /* Get replay info */ if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) /* Need a better error */ return KRB5_RC_REQUIRED; if (!auth_context->local_addr) return KRB5_LOCAL_ADDR_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) { if ((retval = krb5_us_timeofday(context, &replaydata.timestamp, &replaydata.usec))) return retval; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; } } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { replaydata.seq = auth_context->local_seq_number++; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) outdata->seq = replaydata.seq; } { krb5_address * premote_fulladdr = NULL; krb5_address * plocal_fulladdr; krb5_address remote_fulladdr; krb5_address local_fulladdr; krb5_cksumtype sumtype; CLEANUP_INIT(2); if (auth_context->local_port) { if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, auth_context->local_port, &local_fulladdr))){ CLEANUP_PUSH(local_fulladdr.contents, free); plocal_fulladdr = &local_fulladdr; } else { goto error; } } else { plocal_fulladdr = auth_context->local_addr; } if (auth_context->remote_addr) { if (auth_context->remote_port) { if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, auth_context->remote_port, &remote_fulladdr))){ CLEANUP_PUSH(remote_fulladdr.contents, free); premote_fulladdr = &remote_fulladdr; } else { CLEANUP_DONE(); goto error; } } else { premote_fulladdr = auth_context->remote_addr; } } { krb5_enctype enctype = krb5_k_key_enctype(context, key); unsigned int nsumtypes; unsigned int i; krb5_cksumtype *sumtypes; retval = krb5_c_keyed_checksum_types (context, enctype, &nsumtypes, &sumtypes); if (retval) { CLEANUP_DONE (); goto error; } if (nsumtypes == 0) { retval = KRB5_BAD_ENCTYPE; krb5_free_cksumtypes (context, sumtypes); CLEANUP_DONE (); goto error; } for (i = 0; i < nsumtypes; i++) if (auth_context->safe_cksumtype == sumtypes[i]) break; krb5_free_cksumtypes (context, sumtypes); if (i < nsumtypes) sumtype = auth_context->safe_cksumtype; else { switch (enctype) { case ENCTYPE_DES_CBC_MD4: sumtype = CKSUMTYPE_RSA_MD4_DES; break; case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES_CBC_CRC: sumtype = CKSUMTYPE_RSA_MD5_DES; break; default: retval = krb5int_c_mandatory_cksumtype(context, enctype, &sumtype); if (retval) { CLEANUP_DONE(); goto error; } break; } } } if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata, plocal_fulladdr, premote_fulladdr, sumtype, outbuf))) { CLEANUP_DONE(); goto error; } CLEANUP_DONE(); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5_gen_replay_name(context, auth_context->local_addr, "_safe", &replay.client))) { free(outbuf); goto error; } replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { /* should we really error out here? XXX */ free(outbuf); goto error; } free(replay.client); } return 0; error: if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) auth_context->local_seq_number--; return retval; }
krb5_error_code KRB5_CALLCONV krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata) { krb5_error_code retval; krb5_key key; krb5_replay_data replaydata; if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) /* Need a better error */ return KRB5_RC_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->remote_addr == NULL)) return KRB5_REMOTE_ADDR_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; /* Get key */ if ((key = auth_context->recv_subkey) == NULL) key = auth_context->key; memset(&replaydata, 0, sizeof(replaydata)); retval = rd_safe_basic(context, auth_context, inbuf, key, &replaydata, outbuf); if (retval) return retval; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5_check_clockskew(context, replaydata.timestamp))) goto error; if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, "_safe", &replay.client))) goto error; replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { free(replay.client); goto error; } free(replay.client); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) { retval = KRB5KRB_AP_ERR_BADORDER; goto error; } auth_context->remote_seq_number++; } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; outdata->seq = replaydata.seq; } /* everything is ok - return data to the user */ return 0; error: free(outbuf->data); return retval; }
/* * This functions takes as input an array of krb5_credentials, and * outputs an encoded KRB_CRED message suitable for krb5_rd_cred */ krb5_error_code KRB5_CALLCONV krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds **ppcreds, krb5_data **ppdata, krb5_replay_data *outdata) { krb5_address * premote_fulladdr = NULL; krb5_address * plocal_fulladdr = NULL; krb5_address remote_fulladdr; krb5_address local_fulladdr; krb5_error_code retval; krb5_key key; krb5_replay_data replaydata; krb5_cred * pcred; krb5_int32 ncred; krb5_boolean increased_sequence = FALSE; local_fulladdr.contents = 0; remote_fulladdr.contents = 0; memset(&replaydata, 0, sizeof(krb5_replay_data)); if (ppcreds == NULL) return KRB5KRB_AP_ERR_BADADDR; /* * Allocate memory for a NULL terminated list of tickets. */ for (ncred = 0; ppcreds[ncred]; ncred++) ; if ((pcred = (krb5_cred *)calloc(1, sizeof(krb5_cred))) == NULL) return ENOMEM; if ((pcred->tickets = (krb5_ticket **)calloc((size_t)ncred+1, sizeof(krb5_ticket *))) == NULL) { retval = ENOMEM; goto error; } /* Get keyblock */ if ((key = auth_context->send_subkey) == NULL) key = auth_context->key; /* Get replay info */ if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) { retval = KRB5_RC_REQUIRED; goto error; } if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) { /* Need a better error */ retval = KRB5_RC_REQUIRED; goto error; } if ((retval = krb5_us_timeofday(context, &replaydata.timestamp, &replaydata.usec))) goto error; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { replaydata.seq = auth_context->local_seq_number++; increased_sequence = TRUE; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) outdata->seq = replaydata.seq; } if (auth_context->local_addr) { if (auth_context->local_port) { if ((retval = krb5_make_fulladdr(context, auth_context->local_addr, auth_context->local_port, &local_fulladdr))) goto error; plocal_fulladdr = &local_fulladdr; } else { plocal_fulladdr = auth_context->local_addr; } } if (auth_context->remote_addr) { if (auth_context->remote_port) { if ((retval = krb5_make_fulladdr(context,auth_context->remote_addr, auth_context->remote_port, &remote_fulladdr))) goto error; premote_fulladdr = &remote_fulladdr; } else { premote_fulladdr = auth_context->remote_addr; } } /* Setup creds structure */ if ((retval = krb5_mk_ncred_basic(context, ppcreds, ncred, key, &replaydata, plocal_fulladdr, premote_fulladdr, pcred))) { goto error; } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5_gen_replay_name(context, auth_context->local_addr, "_forw", &replay.client))) goto error; replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { /* should we really error out here? XXX */ free(replay.client); goto error; } free(replay.client); } /* Encode creds structure */ retval = encode_krb5_cred(pcred, ppdata); error: free(local_fulladdr.contents); free(remote_fulladdr.contents); krb5_free_cred(context, pcred); if (retval) { if (increased_sequence) auth_context->local_seq_number--; } return retval; }
/* * This functions takes as input an KRB_CRED message, validates it, and * outputs the array of the forwarded credentials and replay cache information */ krb5_error_code KRB5_CALLCONV krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data *pcreddata, krb5_creds ***pppcreds, krb5_replay_data *outdata) { krb5_error_code retval = 0; krb5_replay_data replaydata; if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && (outdata == NULL)) /* Need a better error */ return KRB5_RC_REQUIRED; if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; /* * If decrypting with the subsession key fails, perhaps the * credentials are stored in the session key so try decrypting with that. */ if (auth_context->recv_subkey == NULL || (retval = krb5_rd_cred_basic(context, pcreddata, auth_context->recv_subkey, &replaydata, pppcreds))) { retval = krb5_rd_cred_basic(context, pcreddata, auth_context->key, &replaydata, pppcreds); if (retval) return retval; } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; if ((retval = krb5_check_clockskew(context, replaydata.timestamp))) goto error; if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, "_forw", &replay.client))) goto error; replay.server = ""; /* XXX */ replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { free(replay.client); goto error; } free(replay.client); } if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { if (auth_context->remote_seq_number != replaydata.seq) { retval = KRB5KRB_AP_ERR_BADORDER; goto error; } auth_context->remote_seq_number++; } if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { outdata->timestamp = replaydata.timestamp; outdata->usec = replaydata.usec; outdata->seq = replaydata.seq; } error:; if (retval) { krb5_free_tgt_creds(context, *pppcreds); *pppcreds = NULL; } return retval; }