/* Increment st->counter using least significant byte first. */ static void inc_counter(struct fortuna_state *st) { UINT64_TYPE val; val = load_64_le(st->counter) + 1; store_64_le(val, st->counter); if (val == 0) { val = load_64_le(st->counter + 8) + 1; store_64_le(val, st->counter + 8); } }
krb5_error_code k5_pac_validate_client(krb5_context context, const krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal) { krb5_error_code ret; krb5_data client_info; char *pac_princname; unsigned char *p; krb5_timestamp pac_authtime; krb5_ui_2 pac_princname_length; krb5_int64 pac_nt_authtime; krb5_principal pac_principal; ret = k5_pac_locate_buffer(context, pac, PAC_CLIENT_INFO, &client_info); if (ret != 0) return ret; if (client_info.length < PAC_CLIENT_INFO_LENGTH) return ERANGE; p = (unsigned char *)client_info.data; pac_nt_authtime = load_64_le(p); p += 8; pac_princname_length = load_16_le(p); p += 2; ret = k5_time_to_seconds_since_1970(pac_nt_authtime, &pac_authtime); if (ret != 0) return ret; if (client_info.length < PAC_CLIENT_INFO_LENGTH + pac_princname_length || pac_princname_length % 2) return ERANGE; ret = krb5int_ucs2lecs_to_utf8s(p, (size_t)pac_princname_length / 2, &pac_princname, NULL); if (ret != 0) return ret; ret = krb5_parse_name_flags(context, pac_princname, 0, &pac_principal); if (ret != 0) { free(pac_princname); return ret; } free(pac_princname); if (pac_authtime != authtime || !krb5_principal_compare_flags(context, pac_principal, principal, KRB5_PRINCIPAL_COMPARE_IGNORE_REALM)) ret = KRB5KRB_AP_WRONG_PRINC; krb5_free_principal(context, pac_principal); return ret; }
int main () { /* Test some low-level assumptions the Kerberos code depends on. */ union { uint64_t n64; uint32_t n32; uint16_t n16; unsigned char b[9]; } u; static unsigned char buf[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; assert(load_64_be(buf+1) == 0x0102030405060708LL); assert(load_64_le(buf+1) == 0x0807060504030201LL); assert(load_32_le(buf+2) == 0x05040302); assert(load_32_be(buf+2) == 0x02030405); assert(load_16_be(buf+3) == 0x0304); assert(load_16_le(buf+3) == 0x0403); u.b[0] = 0; assert((store_64_be(0x0102030405060708LL, u.b+1), !memcmp(buf, u.b, 9))); u.b[1] = 9; assert((store_64_le(0x0807060504030201LL, u.b+1), !memcmp(buf, u.b, 9))); u.b[2] = 10; assert((store_32_be(0x02030405, u.b+2), !memcmp(buf, u.b, 9))); u.b[3] = 11; assert((store_32_le(0x05040302, u.b+2), !memcmp(buf, u.b, 9))); u.b[4] = 12; assert((store_16_be(0x0304, u.b+3), !memcmp(buf, u.b, 9))); u.b[4] = 13; assert((store_16_le(0x0403, u.b+3), !memcmp(buf, u.b, 9))); /* Verify that load_*_n properly does native format. Assume the unaligned thing is okay. */ u.n64 = 0x090a0b0c0d0e0f00LL; assert(load_64_n((unsigned char *) &u.n64) == 0x090a0b0c0d0e0f00LL); u.n32 = 0x06070809; assert(load_32_n((unsigned char *) &u.n32) == 0x06070809); u.n16 = 0x0a0b; assert(load_16_n((unsigned char *) &u.n16) == 0x0a0b); return 0; }
/* * Parse the supplied data into the PAC allocated by this function */ krb5_error_code KRB5_CALLCONV krb5_pac_parse(krb5_context context, const void *ptr, size_t len, krb5_pac *ppac) { krb5_error_code ret; size_t i; const unsigned char *p = (const unsigned char *)ptr; krb5_pac pac; size_t header_len; krb5_ui_4 cbuffers, version; *ppac = NULL; if (len < PACTYPE_LENGTH) return ERANGE; cbuffers = load_32_le(p); p += 4; version = load_32_le(p); p += 4; if (version != 0) return EINVAL; header_len = PACTYPE_LENGTH + (cbuffers * PAC_INFO_BUFFER_LENGTH); if (len < header_len) return ERANGE; ret = krb5_pac_init(context, &pac); if (ret != 0) return ret; pac->pac = (PACTYPE *)realloc(pac->pac, sizeof(PACTYPE) + ((cbuffers - 1) * sizeof(PAC_INFO_BUFFER))); if (pac->pac == NULL) { krb5_pac_free(context, pac); return ENOMEM; } pac->pac->cBuffers = cbuffers; pac->pac->Version = version; for (i = 0; i < pac->pac->cBuffers; i++) { PAC_INFO_BUFFER *buffer = &pac->pac->Buffers[i]; buffer->ulType = load_32_le(p); p += 4; buffer->cbBufferSize = load_32_le(p); p += 4; buffer->Offset = load_64_le(p); p += 8; if (buffer->Offset % PAC_ALIGNMENT) { krb5_pac_free(context, pac); return EINVAL; } if (buffer->Offset < header_len || buffer->Offset + buffer->cbBufferSize > len) { krb5_pac_free(context, pac); return ERANGE; } } pac->data.data = realloc(pac->data.data, len); if (pac->data.data == NULL) { krb5_pac_free(context, pac); return ENOMEM; } memcpy(pac->data.data, ptr, len); pac->data.length = len; *ppac = pac; return 0; }