From ea0c76f7a79ee8065ade9b57f7a40de219233498 Mon Sep 17 00:00:00 2001 From: Zhanna Tsitkov Date: Fri, 8 Jan 2010 19:35:40 +0000 Subject: [PATCH] Move kdc related functionality from pac.c into pac_sign.c git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23613 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/krb/Makefile.in | 7 +- src/lib/krb5/krb/authdata.h | 71 +++++++- src/lib/krb5/krb/pac.c | 302 +---------------------------------- src/lib/krb5/krb/pac_sign.c | 278 ++++++++++++++++++++++++++++++++ src/lib/krb5/os/locate_kdc.c | 12 +- 5 files changed, 363 insertions(+), 307 deletions(-) create mode 100644 src/lib/krb5/krb/pac_sign.c diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index 7b640f1ca..51f2f15c3 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -71,6 +71,7 @@ STLIBOBJS= \ mk_req_ext.o \ mk_safe.o \ pac.o \ + pac_sign.o \ parse.o \ pr_to_salt.o \ preauth.o \ @@ -167,6 +168,7 @@ OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ $(OUTPRE)mk_req_ext.$(OBJEXT) \ $(OUTPRE)mk_safe.$(OBJEXT) \ $(OUTPRE)pac.$(OBJEXT) \ + $(OUTPRE)pac_sign.$(OBJEXT) \ $(OUTPRE)parse.$(OBJEXT) \ $(OUTPRE)pr_to_salt.$(OBJEXT) \ $(OUTPRE)preauth.$(OBJEXT) \ @@ -264,6 +266,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/mk_req_ext.c \ $(srcdir)/mk_safe.c \ $(srcdir)/pac.c \ + $(srcdir)/pac_sign.c \ $(srcdir)/parse.c \ $(srcdir)/pr_to_salt.c \ $(srcdir)/preauth.c \ @@ -331,12 +334,12 @@ T_WALK_RTREE_OBJS= t_walk_rtree.o walk_rtree.o tgtname.o unparse.o \ T_KERB_OBJS= t_kerb.o conv_princ.o unparse.o set_realm.o str_conv.o T_SER_OBJS= t_ser.o ser_actx.o ser_adata.o ser_addr.o ser_auth.o ser_cksum.o \ - ser_ctx.o ser_key.o ser_princ.o serialize.o authdata.o pac.o \ + ser_ctx.o ser_key.o ser_princ.o serialize.o authdata.o pac.o pac_sign.o \ copy_data.o etype_list.o T_DELTAT_OBJS= t_deltat.o deltat.o -T_PAC_OBJS= t_pac.o pac.o copy_data.o +T_PAC_OBJS= t_pac.o pac.o pac_sign.o copy_data.o T_PRINC_OBJS= t_princ.o parse.o unparse.o diff --git a/src/lib/krb5/krb/authdata.h b/src/lib/krb5/krb/authdata.h index 39d80d662..090ce336a 100644 --- a/src/lib/krb5/krb/authdata.h +++ b/src/lib/krb5/krb/authdata.h @@ -32,6 +32,8 @@ #define KRB_AUTHDATA_H #include +#include "k5-utf8.h" + /* authdata.c */ krb5_error_code @@ -42,7 +44,74 @@ krb5int_authdata_verify(krb5_context context, const krb5_keyblock *key, const krb5_ap_req *ap_req); -/* pac.c */ +/* PAC */ +/* + * A PAC consists of a sequence of PAC_INFO_BUFFERs, preceeded by + * a PACTYPE header. Decoding the contents of the buffers is left + * to the application (notwithstanding signature verification). + */ + +typedef struct _PAC_INFO_BUFFER { + krb5_ui_4 ulType; + krb5_ui_4 cbBufferSize; + krb5_ui_8 Offset; +} PAC_INFO_BUFFER; + +typedef struct _PACTYPE { + krb5_ui_4 cBuffers; + krb5_ui_4 Version; + PAC_INFO_BUFFER Buffers[1]; +} PACTYPE; + +struct krb5_pac_data { + PACTYPE *pac; /* PAC header + info buffer array */ + krb5_data data; /* PAC data (including uninitialised header) */ + krb5_boolean verified; +}; + + + +#define PAC_ALIGNMENT 8 +#define PACTYPE_LENGTH 8U +#define PAC_SIGNATURE_DATA_LENGTH 4U +#define PAC_CLIENT_INFO_LENGTH 10U +#define PAC_INFO_BUFFER_LENGTH 16 +/* ulType */ +#define PAC_LOGON_INFO 1 +#define PAC_CREDENTIALS_INFO 2 +#define PAC_SERVER_CHECKSUM 6 +#define PAC_PRIVSVR_CHECKSUM 7 +#define PAC_CLIENT_INFO 10 +#define PAC_DELEGATION_INFO 11 +#define PAC_UPN_DNS_INFO 12 + +#define NT_TIME_EPOCH 11644473600LL + extern krb5plugin_authdata_client_ftable_v0 krb5int_mspac_authdata_client_ftable; +krb5_error_code +k5_pac_locate_buffer(krb5_context context, + const krb5_pac pac, + krb5_ui_4 type, + krb5_data *data); + +krb5_error_code +k5_pac_validate_client(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal); + +krb5_error_code +k5_pac_add_buffer(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_data *data, + krb5_boolean zerofill, + krb5_data *out_data); + +krb5_error_code +k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds, + krb5_ui_8 *ntTime); + + #endif /* !KRB_AUTHDATA_H */ diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c index cda09b255..b3be61c84 100644 --- a/src/lib/krb5/krb/pac.c +++ b/src/lib/krb5/krb/pac.c @@ -27,63 +27,14 @@ */ #include "k5-int.h" -#include "k5-utf8.h" #include "authdata.h" /* draft-brezak-win2k-krb-authz-00 */ -/* - * A PAC consists of a sequence of PAC_INFO_BUFFERs, preceeded by - * a PACTYPE header. Decoding the contents of the buffers is left - * to the application (notwithstanding signature verification). - */ - -typedef struct _PAC_INFO_BUFFER { - krb5_ui_4 ulType; - krb5_ui_4 cbBufferSize; - krb5_ui_8 Offset; -} PAC_INFO_BUFFER; - -#define PAC_INFO_BUFFER_LENGTH 16 - -/* ulType */ -#define PAC_LOGON_INFO 1 -#define PAC_CREDENTIALS_INFO 2 -#define PAC_SERVER_CHECKSUM 6 -#define PAC_PRIVSVR_CHECKSUM 7 -#define PAC_CLIENT_INFO 10 -#define PAC_DELEGATION_INFO 11 -#define PAC_UPN_DNS_INFO 12 - -typedef struct _PACTYPE { - krb5_ui_4 cBuffers; - krb5_ui_4 Version; - PAC_INFO_BUFFER Buffers[1]; -} PACTYPE; - -#define PAC_ALIGNMENT 8 -#define PACTYPE_LENGTH 8U -#define PAC_SIGNATURE_DATA_LENGTH 4U -#define PAC_CLIENT_INFO_LENGTH 10U - -#define NT_TIME_EPOCH 11644473600LL - -struct krb5_pac_data { - PACTYPE *pac; /* PAC header + info buffer array */ - krb5_data data; /* PAC data (including uninitialised header) */ - krb5_boolean verified; -}; - -static krb5_error_code -k5_pac_locate_buffer(krb5_context context, - const krb5_pac pac, - krb5_ui_4 type, - krb5_data *data); - /* * Add a buffer to the provided PAC and update header. */ -static krb5_error_code +krb5_error_code k5_pac_add_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, @@ -187,7 +138,7 @@ krb5_pac_free(krb5_context context, } } -static krb5_error_code +krb5_error_code k5_pac_locate_buffer(krb5_context context, const krb5_pac pac, krb5_ui_4 type, @@ -447,7 +398,7 @@ k5_time_to_seconds_since_1970(krb5_int64 ntTime, return 0; } -static krb5_error_code +krb5_error_code k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds, krb5_ui_8 *ntTime) { @@ -461,7 +412,7 @@ k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds, return 0; } -static krb5_error_code +krb5_error_code k5_pac_validate_client(krb5_context context, const krb5_pac pac, krb5_timestamp authtime, @@ -702,251 +653,6 @@ krb5_pac_verify(krb5_context context, return 0; } -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, - 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, 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; -} - -static krb5_error_code -k5_insert_checksum(krb5_context context, - krb5_pac pac, - krb5_ui_4 type, - const krb5_keyblock *key, - krb5_cksumtype *cksumtype) -{ - krb5_error_code ret; - size_t len; - krb5_data cksumdata; - - ret = krb5int_c_mandatory_cksumtype(context, key->enctype, cksumtype); - if (ret != 0) - return ret; - - ret = krb5_c_checksum_length(context, *cksumtype, &len); - if (ret != 0) - return ret; - - ret = k5_pac_locate_buffer(context, pac, type, &cksumdata); - if (ret == 0) { - /* - * If we're resigning PAC, make sure we can fit checksum - * into existing buffer - */ - if (cksumdata.length != PAC_SIGNATURE_DATA_LENGTH + len) - return ERANGE; - - memset(cksumdata.data, 0, cksumdata.length); - } else { - /* Add a zero filled buffer */ - cksumdata.length = PAC_SIGNATURE_DATA_LENGTH + len; - cksumdata.data = NULL; - - ret = k5_pac_add_buffer(context, pac, - type, &cksumdata, - TRUE, &cksumdata); - if (ret != 0) - return ret; - } - - /* Encode checksum type into buffer */ - store_32_le((krb5_ui_4)*cksumtype, cksumdata.data); - - 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; -} - -krb5_error_code KRB5_CALLCONV -krb5int_pac_sign(krb5_context context, - krb5_pac pac, - krb5_timestamp authtime, - krb5_const_principal principal, - const krb5_keyblock *server_key, - const krb5_keyblock *privsvr_key, - krb5_data *data) -{ - krb5_error_code ret; - krb5_data server_cksum, privsvr_cksum; - krb5_cksumtype server_cksumtype, privsvr_cksumtype; - krb5_crypto_iov iov[2]; - - data->length = 0; - data->data = NULL; - - if (principal != NULL) { - ret = k5_insert_client_info(context, pac, authtime, principal); - if (ret != 0) - return ret; - } - - /* Create zeroed buffers for both checksums */ - ret = k5_insert_checksum(context, pac, PAC_SERVER_CHECKSUM, - server_key, &server_cksumtype); - if (ret != 0) - return ret; - - ret = k5_insert_checksum(context, pac, PAC_PRIVSVR_CHECKSUM, - privsvr_key, &privsvr_cksumtype); - if (ret != 0) - return ret; - - /* Now, encode the PAC header so that the checksums will include it */ - ret = k5_pac_encode_header(context, pac); - if (ret != 0) - return ret; - - /* Generate the server checksum over the entire PAC */ - ret = k5_pac_locate_buffer(context, pac, - PAC_SERVER_CHECKSUM, &server_cksum); - if (ret != 0) - return ret; - - assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH); - - iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - iov[0].data = pac->data; - - iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; - iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; - iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; - - ret = krb5_c_make_checksum_iov(context, server_cksumtype, - server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, - iov, sizeof(iov)/sizeof(iov[0])); - if (ret != 0) - return ret; - - /* Generate the privsvr checksum over the server checksum buffer */ - ret = k5_pac_locate_buffer(context, pac, - PAC_PRIVSVR_CHECKSUM, &privsvr_cksum); - if (ret != 0) - return ret; - - assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH); - - iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; - iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; - - iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; - iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH; - iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH; - - ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype, - privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, - iov, sizeof(iov)/sizeof(iov[0])); - if (ret != 0) - return ret; - - data->data = malloc(pac->data.length); - if (data->data == NULL) - return ENOMEM; - - data->length = pac->data.length; - - memcpy(data->data, pac->data.data, pac->data.length); - memset(pac->data.data, 0, - PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH)); - - return 0; -} - /* * PAC auth data attribute backend */ diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c new file mode 100644 index 000000000..7cee3a9ed --- /dev/null +++ b/src/lib/krb5/krb/pac_sign.c @@ -0,0 +1,278 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * lib/krb5/krb/pac.c + * + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * krb5int_pac_sign() + */ + +#include "k5-int.h" +#include "authdata.h" + +/* draft-brezak-win2k-krb-authz-00 */ + +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, + 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, 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; +} + +static krb5_error_code +k5_insert_checksum(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_keyblock *key, + krb5_cksumtype *cksumtype) +{ + krb5_error_code ret; + size_t len; + krb5_data cksumdata; + + ret = krb5int_c_mandatory_cksumtype(context, key->enctype, cksumtype); + if (ret != 0) + return ret; + + ret = krb5_c_checksum_length(context, *cksumtype, &len); + if (ret != 0) + return ret; + + ret = k5_pac_locate_buffer(context, pac, type, &cksumdata); + if (ret == 0) { + /* + * If we're resigning PAC, make sure we can fit checksum + * into existing buffer + */ + if (cksumdata.length != PAC_SIGNATURE_DATA_LENGTH + len) + return ERANGE; + + memset(cksumdata.data, 0, cksumdata.length); + } else { + /* Add a zero filled buffer */ + cksumdata.length = PAC_SIGNATURE_DATA_LENGTH + len; + cksumdata.data = NULL; + + ret = k5_pac_add_buffer(context, pac, + type, &cksumdata, + TRUE, &cksumdata); + if (ret != 0) + return ret; + } + + /* Encode checksum type into buffer */ + store_32_le((krb5_ui_4)*cksumtype, cksumdata.data); + + 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; +} + +krb5_error_code KRB5_CALLCONV +krb5int_pac_sign(krb5_context context, + krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data server_cksum, privsvr_cksum; + krb5_cksumtype server_cksumtype, privsvr_cksumtype; + krb5_crypto_iov iov[2]; + + data->length = 0; + data->data = NULL; + + if (principal != NULL) { + ret = k5_insert_client_info(context, pac, authtime, principal); + if (ret != 0) + return ret; + } + + /* Create zeroed buffers for both checksums */ + ret = k5_insert_checksum(context, pac, PAC_SERVER_CHECKSUM, + server_key, &server_cksumtype); + if (ret != 0) + return ret; + + ret = k5_insert_checksum(context, pac, PAC_PRIVSVR_CHECKSUM, + privsvr_key, &privsvr_cksumtype); + if (ret != 0) + return ret; + + /* Now, encode the PAC header so that the checksums will include it */ + ret = k5_pac_encode_header(context, pac); + if (ret != 0) + return ret; + + /* Generate the server checksum over the entire PAC */ + ret = k5_pac_locate_buffer(context, pac, + PAC_SERVER_CHECKSUM, &server_cksum); + if (ret != 0) + return ret; + + assert(server_cksum.length > PAC_SIGNATURE_DATA_LENGTH); + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = pac->data; + + iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[1].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; + iov[1].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; + + ret = krb5_c_make_checksum_iov(context, server_cksumtype, + server_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, + iov, sizeof(iov)/sizeof(iov[0])); + if (ret != 0) + return ret; + + /* Generate the privsvr checksum over the server checksum buffer */ + ret = k5_pac_locate_buffer(context, pac, + PAC_PRIVSVR_CHECKSUM, &privsvr_cksum); + if (ret != 0) + return ret; + + assert(privsvr_cksum.length > PAC_SIGNATURE_DATA_LENGTH); + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data.data = server_cksum.data + PAC_SIGNATURE_DATA_LENGTH; + iov[0].data.length = server_cksum.length - PAC_SIGNATURE_DATA_LENGTH; + + iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[1].data.data = privsvr_cksum.data + PAC_SIGNATURE_DATA_LENGTH; + iov[1].data.length = privsvr_cksum.length - PAC_SIGNATURE_DATA_LENGTH; + + ret = krb5_c_make_checksum_iov(context, privsvr_cksumtype, + privsvr_key, KRB5_KEYUSAGE_APP_DATA_CKSUM, + iov, sizeof(iov)/sizeof(iov[0])); + if (ret != 0) + return ret; + + data->data = malloc(pac->data.length); + if (data->data == NULL) + return ENOMEM; + + data->length = pac->data.length; + + memcpy(data->data, pac->data.data, pac->data.length); + memset(pac->data.data, 0, + PACTYPE_LENGTH + (pac->pac->cBuffers * PAC_INFO_BUFFER_LENGTH)); + + return 0; +} diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c index 0ecb2d906..27004a9d0 100644 --- a/src/lib/krb5/os/locate_kdc.c +++ b/src/lib/krb5/os/locate_kdc.c @@ -310,7 +310,7 @@ egress: */ static krb5_error_code -krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm, +locate_srv_conf_1(krb5_context context, const krb5_data *realm, const char * name, struct addrlist *addrlist, int get_masters, int socktype, int udpport, int sec_udpport, int family) @@ -491,7 +491,7 @@ krb5_locate_srv_conf(krb5_context context, const krb5_data *realm, { krb5_error_code ret; - ret = krb5_locate_srv_conf_1 (context, realm, name, al, + ret = locate_srv_conf_1 (context, realm, name, al, get_masters, 0, udpport, sec_udpport, 0); if (ret) return ret; @@ -503,7 +503,7 @@ krb5_locate_srv_conf(krb5_context context, const krb5_data *realm, #ifdef KRB5_DNS_LOOKUP static krb5_error_code -krb5_locate_srv_dns_1 (const krb5_data *realm, +locate_srv_dns_1 (const krb5_data *realm, const char *service, const char *protocol, struct addrlist *addrlist, @@ -750,7 +750,7 @@ prof_locate_server (krb5_context context, const krb5_data *realm, return EBUSY; /* XXX */ } - return krb5_locate_srv_conf_1 (context, realm, profname, addrlist, + return locate_srv_conf_1 (context, realm, profname, addrlist, 0, socktype, dflport1, dflport2, family); } @@ -789,12 +789,12 @@ dns_locate_server (krb5_context context, const krb5_data *realm, code = 0; if (socktype == SOCK_DGRAM || socktype == 0) { - code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", addrlist, family); + code = locate_srv_dns_1(realm, dnsname, "_udp", addrlist, family); if (code) Tprintf("dns udp lookup returned error %d\n", code); } if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) { - code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", addrlist, family); + code = locate_srv_dns_1(realm, dnsname, "_tcp", addrlist, family); if (code) Tprintf("dns tcp lookup returned error %d\n", code); } -- 2.26.2