/* 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); } }
static krb5_error_code k5_insert_client_info(krb5_context context, krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal) { krb5_error_code ret; krb5_data client_info; char *princ_name_utf8 = NULL; unsigned char *princ_name_ucs2 = NULL, *p; size_t princ_name_ucs2_len = 0; krb5_ui_8 nt_authtime; /* If we already have a CLIENT_INFO buffer, then just validate it */ if (k5_pac_locate_buffer(context, pac, KRB5_PAC_CLIENT_INFO, &client_info) == 0) { return k5_pac_validate_client(context, pac, authtime, principal); } ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &princ_name_utf8); if (ret != 0) goto cleanup; ret = krb5int_utf8s_to_ucs2les(princ_name_utf8, &princ_name_ucs2, &princ_name_ucs2_len); if (ret != 0) goto cleanup; client_info.length = PAC_CLIENT_INFO_LENGTH + princ_name_ucs2_len; client_info.data = NULL; ret = k5_pac_add_buffer(context, pac, KRB5_PAC_CLIENT_INFO, &client_info, TRUE, &client_info); if (ret != 0) goto cleanup; p = (unsigned char *)client_info.data; /* copy in authtime converted to a 64-bit NT time */ k5_seconds_since_1970_to_time(authtime, &nt_authtime); store_64_le(nt_authtime, p); p += 8; /* copy in number of UCS-2 characters in principal name */ store_16_le(princ_name_ucs2_len, p); p += 2; /* copy in principal name */ memcpy(p, princ_name_ucs2, princ_name_ucs2_len); cleanup: if (princ_name_ucs2 != NULL) free(princ_name_ucs2); krb5_free_unparsed_name(context, princ_name_utf8); 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; }
/* in-place encoding of PAC header */ static krb5_error_code k5_pac_encode_header(krb5_context context, krb5_pac pac) { size_t i; unsigned char *p; size_t header_len; header_len = PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH); assert(pac->data.length >= header_len); p = (unsigned char *)pac->data.data; store_32_le(pac->pac->cBuffers, p); p += 4; store_32_le(pac->pac->Version, p); p += 4; for (i = 0; i < pac->pac->cBuffers; i++) { PAC_INFO_BUFFER *buffer = &pac->pac->Buffers[i]; store_32_le(buffer->ulType, p); p += 4; store_32_le(buffer->cbBufferSize, p); p += 4; store_64_le(buffer->Offset, p); p += 8; assert((buffer->Offset % PAC_ALIGNMENT) == 0); assert(buffer->Offset + buffer->cbBufferSize <= pac->data.length); assert(buffer->Offset >= header_len); if (buffer->Offset % PAC_ALIGNMENT || buffer->Offset + buffer->cbBufferSize > pac->data.length || buffer->Offset < header_len) return ERANGE; } return 0; }