static krb5_error_code fkt_start_seq_get_int(krb5_context context, krb5_keytab id, int flags, int exclusive, krb5_kt_cursor *c) { int8_t pvno, tag; krb5_error_code ret; struct fkt_data *d = id->data; c->fd = open (d->filename, flags); if (c->fd < 0) { ret = errno; krb5_set_error_message(context, ret, N_("keytab %s open failed: %s", ""), d->filename, strerror(ret)); return ret; } rk_cloexec(c->fd); ret = _krb5_xlock(context, c->fd, exclusive, d->filename); if (ret) { close(c->fd); return ret; } c->sp = krb5_storage_from_fd(c->fd); if (c->sp == NULL) { _krb5_xunlock(context, c->fd); close(c->fd); return krb5_enomem(context); } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); ret = krb5_ret_int8(c->sp, &pvno); if(ret) { krb5_storage_free(c->sp); _krb5_xunlock(context, c->fd); close(c->fd); krb5_clear_error_message(context); return ret; } if(pvno != 5) { krb5_storage_free(c->sp); _krb5_xunlock(context, c->fd); close(c->fd); krb5_clear_error_message (context); return KRB5_KEYTAB_BADVNO; } ret = krb5_ret_int8(c->sp, &tag); if (ret) { krb5_storage_free(c->sp); _krb5_xunlock(context, c->fd); close(c->fd); krb5_clear_error_message(context); return ret; } id->version = tag; storage_set_flags(context, c->sp, id->version); return 0; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_ret_creds_tag(krb5_storage *sp, krb5_creds *creds) { krb5_error_code ret; int8_t dummy8; int32_t dummy32, header; memset(creds, 0, sizeof(*creds)); ret = krb5_ret_int32 (sp, &header); if (ret) goto cleanup; if (header & SC_CLIENT_PRINCIPAL) { ret = krb5_ret_principal (sp, &creds->client); if(ret) goto cleanup; } if (header & SC_SERVER_PRINCIPAL) { ret = krb5_ret_principal (sp, &creds->server); if(ret) goto cleanup; } if (header & SC_SESSION_KEY) { ret = krb5_ret_keyblock (sp, &creds->session); if(ret) goto cleanup; } ret = krb5_ret_times (sp, &creds->times); if(ret) goto cleanup; ret = krb5_ret_int8 (sp, &dummy8); if(ret) goto cleanup; ret = krb5_ret_int32 (sp, &dummy32); if(ret) goto cleanup; creds->flags.b = int2TicketFlags(bitswap32(dummy32)); if (header & SC_ADDRESSES) { ret = krb5_ret_addrs (sp, &creds->addresses); if(ret) goto cleanup; } if (header & SC_AUTHDATA) { ret = krb5_ret_authdata (sp, &creds->authdata); if(ret) goto cleanup; } if (header & SC_TICKET) { ret = krb5_ret_data (sp, &creds->ticket); if(ret) goto cleanup; } if (header & SC_SECOND_TICKET) { ret = krb5_ret_data (sp, &creds->second_ticket); if(ret) goto cleanup; } cleanup: if(ret) { #if 0 krb5_free_cred_contents(context, creds); /* XXX */ #endif } return ret; }
static krb5_error_code fkt_next_entry_int(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor, off_t *start, off_t *end) { int32_t len; int ret; int8_t tmp8; int32_t tmp32; off_t pos, curpos; pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); loop: ret = krb5_ret_int32(cursor->sp, &len); if (ret) return ret; if(len < 0) { pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR); goto loop; } ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal); if (ret) goto out; ret = krb5_ret_int32(cursor->sp, &tmp32); entry->timestamp = tmp32; if (ret) goto out; ret = krb5_ret_int8(cursor->sp, &tmp8); if (ret) goto out; entry->vno = tmp8; ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock); if (ret) goto out; /* there might be a 32 bit kvno here * if it's zero, assume that the 8bit one was right, * otherwise trust the new value */ curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); if(len + 4 + pos - curpos == 4) { ret = krb5_ret_int32(cursor->sp, &tmp32); if (ret == 0 && tmp32 != 0) { entry->vno = tmp32; } } if(start) *start = pos; if(end) *end = *start + 4 + len; out: krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) { krb5_error_code ret; int8_t dummy8; int32_t dummy32; memset(creds, 0, sizeof(*creds)); ret = krb5_ret_principal (sp, &creds->client); if(ret) goto cleanup; ret = krb5_ret_principal (sp, &creds->server); if(ret) goto cleanup; ret = krb5_ret_keyblock (sp, &creds->session); if(ret) goto cleanup; ret = krb5_ret_times (sp, &creds->times); if(ret) goto cleanup; ret = krb5_ret_int8 (sp, &dummy8); if(ret) goto cleanup; ret = krb5_ret_int32 (sp, &dummy32); if(ret) goto cleanup; /* * Runtime detect the what is the higher bits of the bitfield. If * any of the higher bits are set in the input data, it's either a * new ticket flag (and this code need to be removed), or it's a * MIT cache (or new Heimdal cache), lets change it to our current * format. */ { uint32_t mask = 0xffff0000; creds->flags.i = 0; creds->flags.b.anonymous = 1; if (creds->flags.i & mask) mask = ~mask; if (dummy32 & mask) dummy32 = bitswap32(dummy32); } creds->flags.i = dummy32; ret = krb5_ret_addrs (sp, &creds->addresses); if(ret) goto cleanup; ret = krb5_ret_authdata (sp, &creds->authdata); if(ret) goto cleanup; ret = krb5_ret_data (sp, &creds->ticket); if(ret) goto cleanup; ret = krb5_ret_data (sp, &creds->second_ticket); cleanup: if(ret) { #if 0 krb5_free_cred_contents(context, creds); /* XXX */ #endif } return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_ret_uint8(krb5_storage *sp, uint8_t *value) { krb5_error_code ret; int8_t v; ret = krb5_ret_int8(sp, &v); if (ret == 0) *value = (uint8_t)v; return ret; }
static void test_int8(krb5_context context, krb5_storage *sp) { krb5_error_code ret; int i; int8_t val[] = { 0, 1, -1, 128, -127 }, v; krb5_storage_truncate(sp, 0); for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { ret = krb5_store_int8(sp, val[i]); if (ret) krb5_err(context, 1, ret, "krb5_store_int8"); krb5_storage_seek(sp, 0, SEEK_SET); ret = krb5_ret_int8(sp, &v); if (ret) krb5_err(context, 1, ret, "krb5_ret_int8"); if (v != val[i]) krb5_errx(context, 1, "store and ret mismatch"); } }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) { krb5_error_code ret; int8_t dummy8; int32_t dummy32; memset(creds, 0, sizeof(*creds)); ret = krb5_ret_principal (sp, &creds->client); if(ret) goto cleanup; ret = krb5_ret_principal (sp, &creds->server); if(ret) goto cleanup; ret = krb5_ret_keyblock (sp, &creds->session); if(ret) goto cleanup; ret = krb5_ret_times (sp, &creds->times); if(ret) goto cleanup; ret = krb5_ret_int8 (sp, &dummy8); if(ret) goto cleanup; ret = krb5_ret_int32 (sp, &dummy32); if(ret) goto cleanup; creds->flags.b = int2TicketFlags(bitswap32(dummy32)); ret = krb5_ret_addrs (sp, &creds->addresses); if(ret) goto cleanup; ret = krb5_ret_authdata (sp, &creds->authdata); if(ret) goto cleanup; ret = krb5_ret_data (sp, &creds->ticket); if(ret) goto cleanup; ret = krb5_ret_data (sp, &creds->second_ticket); cleanup: if(ret) { #if 0 krb5_free_cred_contents(context, creds); /* XXX */ #endif } return ret; }
static krb5_error_code init_fcc (krb5_context context, krb5_ccache id, krb5_storage **ret_sp, int *ret_fd) { int fd; int8_t pvno, tag; krb5_storage *sp; krb5_error_code ret; ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY | O_CLOEXEC, 0); if(ret) return ret; sp = krb5_storage_from_fd(fd); if(sp == NULL) { krb5_clear_error_message(context); ret = ENOMEM; goto out; } krb5_storage_set_eof_code(sp, KRB5_CC_END); ret = krb5_ret_int8(sp, &pvno); if(ret != 0) { if(ret == KRB5_CC_END) { ret = ENOENT; krb5_set_error_message(context, ret, N_("Empty credential cache file: %s", ""), FILENAME(id)); } else krb5_set_error_message(context, ret, N_("Error reading pvno " "in cache file: %s", ""), FILENAME(id)); goto out; } if(pvno != 5) { ret = KRB5_CCACHE_BADVNO; krb5_set_error_message(context, ret, N_("Bad version number in credential " "cache file: %s", ""), FILENAME(id)); goto out; } ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ if(ret != 0) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, "Error reading tag in " "cache file: %s", FILENAME(id)); goto out; } FCACHE(id)->version = tag; storage_set_flags(context, sp, FCACHE(id)->version); switch (tag) { case KRB5_FCC_FVNO_4: { int16_t length; ret = krb5_ret_int16 (sp, &length); if(ret) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, N_("Error reading tag length in " "cache file: %s", ""), FILENAME(id)); goto out; } while(length > 0) { int16_t dtag, data_len; int i; int8_t dummy; ret = krb5_ret_int16 (sp, &dtag); if(ret) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, N_("Error reading dtag in " "cache file: %s", ""), FILENAME(id)); goto out; } ret = krb5_ret_int16 (sp, &data_len); if(ret) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, N_("Error reading dlength " "in cache file: %s",""), FILENAME(id)); goto out; } switch (dtag) { case FCC_TAG_DELTATIME : ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); if(ret) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, N_("Error reading kdc_sec in " "cache file: %s", ""), FILENAME(id)); goto out; } ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); if(ret) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, N_("Error reading kdc_usec in " "cache file: %s", ""), FILENAME(id)); goto out; } break; default : for (i = 0; i < data_len; ++i) { ret = krb5_ret_int8 (sp, &dummy); if(ret) { ret = KRB5_CC_FORMAT; krb5_set_error_message(context, ret, N_("Error reading unknown " "tag in cache file: %s", ""), FILENAME(id)); goto out; } } break; } length -= 4 + data_len; } break; } case KRB5_FCC_FVNO_3: case KRB5_FCC_FVNO_2: case KRB5_FCC_FVNO_1: break; default : ret = KRB5_CCACHE_BADVNO; krb5_set_error_message(context, ret, N_("Unknown version number (%d) in " "credential cache file: %s", ""), (int)tag, FILENAME(id)); goto out; } *ret_sp = sp; *ret_fd = fd; return 0; out: if(sp != NULL) krb5_storage_free(sp); fcc_unlock(context, fd); close(fd); return ret; }
static krb5_error_code KRB5_CALLCONV fkt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) { int ret; int fd; krb5_storage *sp; struct fkt_data *d = id->data; krb5_data keytab; int32_t len; fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); if (fd < 0) { fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if (fd < 0) { ret = errno; krb5_set_error_message(context, ret, N_("open(%s): %s", ""), d->filename, strerror(ret)); return ret; } rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = fkt_setup_keytab(context, id, sp); if(ret) { goto out; } storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb5_ret_int8(sp, &pvno); if(ret) { /* we probably have a zero byte file, so try to set it up properly */ ret = fkt_setup_keytab(context, id, sp); if(ret) { krb5_set_error_message(context, ret, N_("%s: keytab is corrupted: %s", ""), d->filename, strerror(ret)); goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { ret = KRB5_KEYTAB_BADVNO; krb5_set_error_message(context, ret, N_("Bad version in keytab %s", ""), d->filename); goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { krb5_set_error_message(context, ret, N_("failed reading tag from " "keytab %s", ""), d->filename); goto out; } id->version = tag; storage_set_flags(context, sp, id->version); } } { krb5_storage *emem; emem = krb5_storage_emem(); if(emem == NULL) { ret = krb5_enomem(context); goto out; } ret = krb5_kt_store_principal(context, emem, entry->principal); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing principal " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_int32 (emem, entry->timestamp); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing timpstamp " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_int8 (emem, entry->vno % 256); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_kt_store_keyblock (context, d, emem, &entry->keyblock); if(ret) { krb5_storage_free(emem); goto out; } if ((d->flags & KRB5_KT_FL_JAVA) == 0) { ret = krb5_store_int32 (emem, entry->vno); if (ret) { krb5_set_error_message(context, ret, N_("Failed storing extended kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_uint32 (emem, entry->flags); if (ret) { krb5_set_error_message(context, ret, N_("Failed storing extended kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } } ret = krb5_storage_to_data(emem, &keytab); krb5_storage_free(emem); if(ret) { krb5_set_error_message(context, ret, N_("Failed converting keytab entry " "to memory block for keytab %s", ""), d->filename); goto out; } } while(1) { ret = krb5_ret_int32(sp, &len); if(ret == KRB5_KT_END) { len = keytab.length; break; } if(len < 0) { len = -len; if(len >= (int)keytab.length) { krb5_storage_seek(sp, -4, SEEK_CUR); break; } } krb5_storage_seek(sp, len, SEEK_CUR); } ret = krb5_store_int32(sp, len); if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) { ret = errno; krb5_set_error_message(context, ret, N_("Failed writing keytab block " "in keytab %s: %s", ""), d->filename, strerror(ret)); } memset(keytab.data, 0, keytab.length); krb5_data_free(&keytab); out: krb5_storage_free(sp); _krb5_xunlock(context, fd); close(fd); return ret; }
static krb5_error_code fkt_next_entry_int(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor, off_t *start, off_t *end) { struct fkt_data *d = id->data; int32_t len; int ret; int8_t tmp8; int32_t tmp32; uint32_t utmp32; off_t pos, curpos; pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); loop: ret = krb5_ret_int32(cursor->sp, &len); if (ret) return ret; if(len < 0) { pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR); goto loop; } ret = krb5_kt_ret_principal (context, d, cursor->sp, &entry->principal); if (ret) goto out; ret = krb5_ret_uint32(cursor->sp, &utmp32); entry->timestamp = utmp32; if (ret) goto out; ret = krb5_ret_int8(cursor->sp, &tmp8); if (ret) goto out; entry->vno = tmp8; ret = krb5_kt_ret_keyblock (context, d, cursor->sp, &entry->keyblock); if (ret) goto out; /* there might be a 32 bit kvno here * if it's zero, assume that the 8bit one was right, * otherwise trust the new value */ curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); if(len + 4 + pos - curpos >= 4) { ret = krb5_ret_int32(cursor->sp, &tmp32); if (ret == 0 && tmp32 != 0) entry->vno = tmp32; } /* there might be a flags field here */ if(len + 4 + pos - curpos >= 8) { ret = krb5_ret_uint32(cursor->sp, &utmp32); if (ret == 0) entry->flags = utmp32; } else entry->flags = 0; entry->aliases = NULL; if(start) *start = pos; if(end) *end = pos + 4 + len; out: if (ret) krb5_kt_free_entry(context, entry); krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); return ret; }
/* * Request: * NameZ * ServerPrincipalPresent * ServerPrincipal OPTIONAL * Key * * Repsonse: * */ static krb5_error_code kcm_op_get_initial_ticket(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { krb5_error_code ret; kcm_ccache ccache; char *name; int8_t not_tgt = 0; krb5_principal server = NULL; krb5_keyblock key; krb5_keyblock_zero(&key); ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = krb5_ret_int8(request, ¬_tgt); if (ret) { free(name); return ret; } if (not_tgt) { ret = krb5_ret_principal(request, &server); if (ret) { free(name); return ret; } } ret = krb5_ret_keyblock(request, &key); if (ret) { free(name); if (server != NULL) krb5_free_principal(context, server); return ret; } ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); if (ret == 0) { HEIMDAL_MUTEX_lock(&ccache->mutex); if (ccache->server != NULL) { krb5_free_principal(context, ccache->server); ccache->server = NULL; } krb5_free_keyblock(context, &ccache->key.keyblock); ccache->server = server; ccache->key.keyblock = key; ccache->flags |= KCM_FLAGS_USE_CACHED_KEY; ret = kcm_ccache_enqueue_default(context, ccache, NULL); if (ret) { ccache->server = NULL; krb5_keyblock_zero(&ccache->key.keyblock); ccache->flags &= ~(KCM_FLAGS_USE_CACHED_KEY); } HEIMDAL_MUTEX_unlock(&ccache->mutex); } free(name); if (ret != 0) { krb5_free_principal(context, server); krb5_free_keyblock(context, &key); } kcm_release_ccache(context, ccache); return ret; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_rd_req(krb5_context context, krb5_data *authent, const char *service, const char *instance, const char *local_realm, int32_t from_addr, const krb5_keyblock *key, struct _krb5_krb_auth_data *ad) { krb5_error_code ret; krb5_storage *sp; krb5_data ticket, eaut, aut; krb5_ssize_t size; int little_endian; int8_t pvno; int8_t type; int8_t s_kvno; uint8_t ticket_length; uint8_t eaut_length; uint8_t time_5ms; char *realm = NULL; char *sname = NULL; char *sinstance = NULL; char *r_realm = NULL; char *r_name = NULL; char *r_instance = NULL; uint32_t r_time_sec; /* Coarse time from authenticator */ unsigned long delta_t; /* Time in authenticator - local time */ long tkt_age; /* Age of ticket */ struct timeval tv; krb5_data_zero(&ticket); krb5_data_zero(&eaut); krb5_data_zero(&aut); sp = krb5_storage_from_data(authent); if (sp == NULL) { krb5_set_error_string(context, "alloc: out of memory"); return ENOMEM; } krb5_storage_set_eof_code(sp, EINVAL); /* XXX */ ret = krb5_ret_int8(sp, &pvno); if (ret) goto error; if (pvno != KRB_PROT_VERSION) { ret = EINVAL; /* XXX */ goto error; } ret = krb5_ret_int8(sp, &type); if (ret) goto error; little_endian = type & 1; type &= ~1; if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) { ret = EINVAL; /* RD_AP_MSG_TYPE */ goto error; } RCHECK(ret, krb5_ret_int8(sp, &s_kvno), error); RCHECK(ret, get_v4_stringz(sp, &realm, REALM_SZ), error); RCHECK(ret, krb5_ret_uint8(sp, &ticket_length), error); RCHECK(ret, krb5_ret_uint8(sp, &eaut_length), error); RCHECK(ret, krb5_data_alloc(&ticket, ticket_length), error); size = krb5_storage_read(sp, ticket.data, ticket.length); if (size != ticket.length) { ret = EINVAL; goto error; } /* Decrypt and take apart ticket */ ret = _krb5_krb_decomp_ticket(context, &ticket, key, local_realm, &sname, &sinstance, ad); if (ret) goto error; RCHECK(ret, krb5_data_alloc(&eaut, eaut_length), error); size = krb5_storage_read(sp, eaut.data, eaut.length); if (size != eaut.length) { ret = EINVAL; goto error; } krb5_storage_free(sp); sp = NULL; ret = decrypt_etext(context, &ad->session, &eaut, &aut); if (ret) goto error; sp = krb5_storage_from_data(&aut); if (sp == NULL) { krb5_set_error_string(context, "alloc: out of memory"); ret = ENOMEM; goto error; } if (little_endian) krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); else krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); RCHECK(ret, get_v4_stringz(sp, &r_name, ANAME_SZ), error); RCHECK(ret, get_v4_stringz(sp, &r_instance, INST_SZ), error); RCHECK(ret, get_v4_stringz(sp, &r_realm, REALM_SZ), error); RCHECK(ret, krb5_ret_uint32(sp, &ad->checksum), error); RCHECK(ret, krb5_ret_uint8(sp, &time_5ms), error); RCHECK(ret, krb5_ret_uint32(sp, &r_time_sec), error); if (strcmp(ad->pname, r_name) != 0 || strcmp(ad->pinst, r_instance) != 0 || strcmp(ad->prealm, r_realm) != 0) { ret = EINVAL; /* RD_AP_INCON */ goto error; } if (from_addr && from_addr != ad->address) { ret = EINVAL; /* RD_AP_BADD */ goto error; } gettimeofday(&tv, NULL); delta_t = abs((int)(tv.tv_sec - r_time_sec)); if (delta_t > CLOCK_SKEW) { ret = EINVAL; /* RD_AP_TIME */ goto error; } /* Now check for expiration of ticket */ tkt_age = tv.tv_sec - ad->time_sec; if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) { ret = EINVAL; /* RD_AP_NYV */ goto error; } if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) { ret = EINVAL; /* RD_AP_EXP */ goto error; } ret = 0; error: krb5_data_free(&ticket); krb5_data_free(&eaut); krb5_data_free(&aut); if (realm) free(realm); if (sname) free(sname); if (sinstance) free(sinstance); if (r_name) free(r_name); if (r_instance) free(r_instance); if (r_realm) free(r_realm); if (sp) krb5_storage_free(sp); if (ret) krb5_clear_error_string(context); return ret; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_decomp_ticket(krb5_context context, const krb5_data *enc_ticket, const krb5_keyblock *key, const char *local_realm, char **sname, char **sinstance, struct _krb5_krb_auth_data *ad) { krb5_error_code ret; krb5_ssize_t size; krb5_storage *sp = NULL; krb5_data ticket; unsigned char des_key[8]; memset(ad, 0, sizeof(*ad)); krb5_data_zero(&ticket); *sname = NULL; *sinstance = NULL; RCHECK(ret, decrypt_etext(context, key, enc_ticket, &ticket), error); sp = krb5_storage_from_data(&ticket); if (sp == NULL) { krb5_data_free(&ticket); krb5_set_error_string(context, "alloc: out of memory"); return ENOMEM; } krb5_storage_set_eof_code(sp, EINVAL); /* XXX */ RCHECK(ret, krb5_ret_int8(sp, &ad->k_flags), error); RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error); RCHECK(ret, get_v4_stringz(sp, &ad->pinst, INST_SZ), error); RCHECK(ret, get_v4_stringz(sp, &ad->prealm, REALM_SZ), error); RCHECK(ret, krb5_ret_uint32(sp, &ad->address), error); size = krb5_storage_read(sp, des_key, sizeof(des_key)); if (size != sizeof(des_key)) { ret = EINVAL; /* XXX */ goto error; } RCHECK(ret, krb5_ret_uint8(sp, &ad->life), error); if (ad->k_flags & 1) krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); else krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); RCHECK(ret, krb5_ret_uint32(sp, &ad->time_sec), error); RCHECK(ret, get_v4_stringz(sp, sname, ANAME_SZ), error); RCHECK(ret, get_v4_stringz(sp, sinstance, INST_SZ), error); ret = krb5_keyblock_init(context, ETYPE_DES_PCBC_NONE, des_key, sizeof(des_key), &ad->session); if (ret) goto error; if (strlen(ad->prealm) == 0) { free(ad->prealm); ad->prealm = strdup(local_realm); if (ad->prealm == NULL) { ret = ENOMEM; goto error; } } error: memset(des_key, 0, sizeof(des_key)); if (sp) krb5_storage_free(sp); krb5_data_free(&ticket); if (ret) { if (*sname) { free(*sname); *sname = NULL; } if (*sinstance) { free(*sinstance); *sinstance = NULL; } _krb5_krb_free_auth_data(context, ad); krb5_set_error_string(context, "Failed to decode v4 ticket"); } return ret; }
static krb5_error_code fkt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) { int ret; int fd; krb5_storage *sp; struct fkt_data *d = id->data; krb5_data keytab; int32_t len; fd = open (d->filename, O_RDWR | O_BINARY); if (fd < 0) { fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); if (fd < 0) { ret = errno; krb5_set_error_string(context, "open(%s): %s", d->filename, strerror(ret)); return ret; } ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = fkt_setup_keytab(context, id, sp); if(ret) { goto out; } storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb5_ret_int8(sp, &pvno); if(ret) { /* we probably have a zero byte file, so try to set it up properly */ ret = fkt_setup_keytab(context, id, sp); if(ret) { krb5_set_error_string(context, "%s: keytab is corrupted: %s", d->filename, strerror(ret)); goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { ret = KRB5_KEYTAB_BADVNO; krb5_set_error_string(context, "%s: %s", d->filename, strerror(ret)); goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { krb5_set_error_string(context, "%s: reading tag: %s", d->filename, strerror(ret)); goto out; } id->version = tag; storage_set_flags(context, sp, id->version); } } { krb5_storage *emem; emem = krb5_storage_emem(); if(emem == NULL) { ret = ENOMEM; krb5_set_error_string (context, "malloc: out of memory"); goto out; } ret = krb5_kt_store_principal(context, emem, entry->principal); if(ret) { krb5_storage_free(emem); goto out; } ret = krb5_store_int32 (emem, entry->timestamp); if(ret) { krb5_storage_free(emem); goto out; } ret = krb5_store_int8 (emem, entry->vno % 256); if(ret) { krb5_storage_free(emem); goto out; } ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock); if(ret) { krb5_storage_free(emem); goto out; } if ((d->flags & KRB5_KT_FL_JAVA) == 0) { ret = krb5_store_int32 (emem, entry->vno); if (ret) { krb5_storage_free(emem); goto out; } } ret = krb5_storage_to_data(emem, &keytab); krb5_storage_free(emem); if(ret) goto out; } while(1) { ret = krb5_ret_int32(sp, &len); if(ret == KRB5_KT_END) { len = keytab.length; break; } if(len < 0) { len = -len; if(len >= keytab.length) { krb5_storage_seek(sp, -4, SEEK_CUR); break; } } krb5_storage_seek(sp, len, SEEK_CUR); } ret = krb5_store_int32(sp, len); if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) ret = errno; memset(keytab.data, 0, keytab.length); krb5_data_free(&keytab); out: krb5_storage_free(sp); _krb5_xunlock(context, fd); close(fd); return ret; }