summaryrefslogtreecommitdiff
path: root/source4/auth/kerberos/kerberos_pac.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-08-05 00:41:53 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:31:15 -0500
commit8db8279730c6d4ef6b03b9f96381dee890a8da57 (patch)
tree718b9b289624d91f50a89d4e579c10393c540027 /source4/auth/kerberos/kerberos_pac.c
parent84da1a1050ee0f0cf5b2ecfec78291424b648c30 (diff)
downloadsamba-8db8279730c6d4ef6b03b9f96381dee890a8da57.tar.gz
samba-8db8279730c6d4ef6b03b9f96381dee890a8da57.tar.bz2
samba-8db8279730c6d4ef6b03b9f96381dee890a8da57.zip
r9084: 'resign' the sample PAC for the validation of the signature algorithms.
If we ever get problems with the kerberos code, it should show up as a different signature in this PAC. This involved returning more data from the pac functions, so changed some callers and split up some functions. Andrew Bartlett (This used to be commit d514a7491208afa0533bf9e99601147eb69e08c9)
Diffstat (limited to 'source4/auth/kerberos/kerberos_pac.c')
-rw-r--r--source4/auth/kerberos/kerberos_pac.c259
1 files changed, 173 insertions, 86 deletions
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index f561bdfe76..83679972d9 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -78,7 +78,7 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
}
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
- struct PAC_LOGON_INFO **logon_info_out,
+ struct PAC_DATA **pac_data_out,
DATA_BLOB blob,
struct smb_krb5_context *smb_krb5_context,
krb5_keyblock *krbtgt_keyblock,
@@ -90,46 +90,50 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
struct PAC_SIGNATURE_DATA kdc_sig;
struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
struct PAC_LOGON_INFO *logon_info = NULL;
- struct PAC_DATA pac_data;
+ struct PAC_DATA *pac_data;
+
DATA_BLOB modified_pac_blob = data_blob_talloc(mem_ctx, blob.data, blob.length);
int i;
- /* file_save("tmp_pac_data.dat",blob.data,blob.length); */
+ pac_data = talloc(mem_ctx, struct PAC_DATA);
+ if (!pac_data) {
+ return NT_STATUS_NO_MEMORY;
+ }
- status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+ status = ndr_pull_struct_blob(&blob, mem_ctx, pac_data,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("can't parse the PAC\n"));
return status;
}
- if (pac_data.num_buffers < 3) {
+ if (pac_data->num_buffers < 3) {
/* we need logon_ingo, service_key and kdc_key */
DEBUG(0,("less than 3 PAC buffers\n"));
return NT_STATUS_FOOBAR;
}
- for (i=0; i < pac_data.num_buffers; i++) {
- switch (pac_data.buffers[i].type) {
+ for (i=0; i < pac_data->num_buffers; i++) {
+ switch (pac_data->buffers[i].type) {
case PAC_TYPE_LOGON_INFO:
- if (!pac_data.buffers[i].info) {
+ if (!pac_data->buffers[i].info) {
break;
}
- logon_info = pac_data.buffers[i].info->logon_info.info;
+ logon_info = pac_data->buffers[i].info->logon_info.info;
break;
case PAC_TYPE_SRV_CHECKSUM:
- if (!pac_data.buffers[i].info) {
+ if (!pac_data->buffers[i].info) {
break;
}
- srv_sig_ptr = &pac_data.buffers[i].info->srv_cksum;
- srv_sig = pac_data.buffers[i].info->srv_cksum;
+ srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
+ srv_sig = pac_data->buffers[i].info->srv_cksum;
break;
case PAC_TYPE_KDC_CHECKSUM:
- if (!pac_data.buffers[i].info) {
+ if (!pac_data->buffers[i].info) {
break;
}
- kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum;
- kdc_sig = pac_data.buffers[i].info->kdc_cksum;
+ kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
+ kdc_sig = pac_data->buffers[i].info->kdc_cksum;
break;
case PAC_TYPE_LOGON_NAME:
break;
@@ -181,16 +185,56 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
}
}
+#if 0
+ if (strcasecmp(logon_info->info3.base.account_name.string,
+ "Administrator")== 0) {
+ file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
+ }
+#endif
+
DEBUG(0,("account_name: %s [%s]\n",
logon_info->info3.base.account_name.string,
logon_info->info3.base.full_name.string));
- *logon_info_out = logon_info;
+ *pac_data_out = pac_data;
return status;
}
+ NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
+ struct PAC_LOGON_INFO **logon_info,
+ DATA_BLOB blob,
+ struct smb_krb5_context *smb_krb5_context,
+ krb5_keyblock *krbtgt_keyblock,
+ krb5_keyblock *service_keyblock)
+{
+ NTSTATUS nt_status;
+ struct PAC_DATA *pac_data;
+ int i;
+
+ nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
+ blob,
+ smb_krb5_context,
+ krbtgt_keyblock,
+ service_keyblock);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ *logon_info = NULL;
+ for (i=0; i < pac_data->num_buffers; i++) {
+ if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) {
+ continue;
+ }
+ *logon_info = pac_data->buffers[i].info->logon_info.info;
+ }
+ if (!*logon_info) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ return NT_STATUS_OK;
+}
+
static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
- DATA_BLOB pac_data,
+ DATA_BLOB *pac_data,
struct PAC_SIGNATURE_DATA *sig,
krb5_context context,
krb5_keyblock *keyblock)
@@ -205,15 +249,16 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
0,
&crypto);
if (ret) {
- DEBUG(0,("krb5_crypto_init() failed\n"));
+ DEBUG(0,("krb5_crypto_init() failed: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
return ret;
}
ret = krb5_create_checksum(context,
crypto,
KRB5_KU_OTHER_CKSUM,
0,
- pac_data.data,
- pac_data.length,
+ pac_data->data,
+ pac_data->length,
&cksum);
if (ret) {
DEBUG(2, ("PAC Verification failed: %s\n",
@@ -235,6 +280,107 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
}
krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
+ struct PAC_DATA *pac_data,
+ krb5_context context,
+ krb5_keyblock *krbtgt_keyblock,
+ krb5_keyblock *service_keyblock,
+ DATA_BLOB *pac)
+{
+ NTSTATUS nt_status;
+ krb5_error_code ret;
+ DATA_BLOB zero_blob = data_blob(NULL, 0);
+ DATA_BLOB tmp_blob = data_blob(NULL, 0);
+ DATA_BLOB service_checksum_blob;
+ struct PAC_SIGNATURE_DATA *kdc_checksum = NULL;
+ struct PAC_SIGNATURE_DATA *srv_checksum = NULL;
+ int i;
+
+ /* First, just get the keytypes filled in (and lengths right, eventually) */
+ for (i=0; i < pac_data->num_buffers; i++) {
+ if (pac_data->buffers[i].type != PAC_TYPE_KDC_CHECKSUM) {
+ continue;
+ }
+ kdc_checksum = &pac_data->buffers[i].info->kdc_cksum,
+ ret = make_pac_checksum(mem_ctx, &zero_blob,
+ kdc_checksum,
+ context, krbtgt_keyblock);
+ if (ret) {
+ DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ talloc_free(pac_data);
+ return ret;
+ }
+ }
+
+ for (i=0; i < pac_data->num_buffers; i++) {
+ if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) {
+ continue;
+ }
+ srv_checksum = &pac_data->buffers[i].info->srv_cksum;
+ ret = make_pac_checksum(mem_ctx, &zero_blob,
+ srv_checksum,
+ context, service_keyblock);
+ if (ret) {
+ DEBUG(2, ("making service PAC checksum failed: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ talloc_free(pac_data);
+ return ret;
+ }
+ }
+
+ if (!kdc_checksum) {
+ DEBUG(2, ("Invalid PAC constructed for signing, no KDC checksum present!"));
+ return EINVAL;
+ }
+ if (!srv_checksum) {
+ DEBUG(2, ("Invalid PAC constructed for signing, no SRV checksum present!"));
+ return EINVAL;
+ }
+
+ /* But wipe out the actual signatures */
+ ZERO_STRUCT(kdc_checksum->signature);
+ ZERO_STRUCT(srv_checksum->signature);
+
+ nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
+ (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
+ talloc_free(pac_data);
+ return EINVAL;
+ }
+
+ /* Then sign the result of the previous push, where the sig was zero'ed out */
+ ret = make_pac_checksum(mem_ctx, &tmp_blob, srv_checksum,
+ context, service_keyblock);
+
+ service_checksum_blob
+ = data_blob_const(srv_checksum->signature, sizeof(srv_checksum->signature));
+
+ /* Then sign Server checksum */
+ ret = make_pac_checksum(mem_ctx, &service_checksum_blob, kdc_checksum, context, krbtgt_keyblock);
+ if (ret) {
+ DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ talloc_free(pac_data);
+ return ret;
+ }
+
+ /* And push it out again, this time to the world. This relies on determanistic pointer values */
+ nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
+ (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
+ talloc_free(pac_data);
+ return EINVAL;
+ }
+
+ *pac = tmp_blob;
+
+ return ret;
+}
+
+
+ krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
struct auth_serversupplied_info *server_info,
krb5_context context,
krb5_keyblock *krbtgt_keyblock,
@@ -242,9 +388,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
DATA_BLOB *pac)
{
NTSTATUS nt_status;
- DATA_BLOB zero_blob = data_blob(NULL, 0);
- DATA_BLOB tmp_blob = data_blob(NULL, 0);
- DATA_BLOB service_checksum_blob;
krb5_error_code ret;
struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
struct netr_SamInfo3 *sam3;
@@ -254,9 +397,7 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
union PAC_INFO *u_LOGON_NAME;
struct PAC_LOGON_NAME *LOGON_NAME;
union PAC_INFO *u_KDC_CHECKSUM;
- struct PAC_SIGNATURE_DATA *KDC_CHECKSUM;
union PAC_INFO *u_SRV_CHECKSUM;
- struct PAC_SIGNATURE_DATA *SRV_CHECKSUM;
enum {
PAC_BUF_LOGON_INFO = 0,
@@ -308,7 +449,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
}
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = u_SRV_CHECKSUM;
- SRV_CHECKSUM = &u_SRV_CHECKSUM->srv_cksum;
/* KDC_CHECKSUM */
u_KDC_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
@@ -318,7 +458,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
}
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = u_KDC_CHECKSUM;
- KDC_CHECKSUM = &u_KDC_CHECKSUM->kdc_cksum;
/* now the real work begins... */
@@ -341,64 +480,12 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
LOGON_NAME->account_name = server_info->account_name;
LOGON_NAME->logon_time = timeval_to_nttime(&tv);
-
-
- /* First, just get the keytypes filled in (and lengths right, eventually) */
- ret = make_pac_checksum(mem_ctx, zero_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
- if (ret) {
- DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- talloc_free(pac_data);
- return ret;
- }
-
- ret = make_pac_checksum(mem_ctx, zero_blob, SRV_CHECKSUM, context, service_keyblock);
- if (ret) {
- DEBUG(2, ("making service PAC checksum failed: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- talloc_free(pac_data);
- return ret;
- }
-
- /* But wipe out the actual signatures */
- ZERO_STRUCT(KDC_CHECKSUM->signature);
- ZERO_STRUCT(SRV_CHECKSUM->signature);
-
- nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
- (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
- talloc_free(pac_data);
- return EINVAL;
- }
-
- /* Then sign the result of the previous push, where the sig was zero'ed out */
- ret = make_pac_checksum(mem_ctx, tmp_blob, SRV_CHECKSUM,
- context, service_keyblock);
-
- service_checksum_blob
- = data_blob_const(SRV_CHECKSUM->signature, sizeof(SRV_CHECKSUM->signature));
-
- /* Then sign Server checksum */
- ret = make_pac_checksum(mem_ctx, service_checksum_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
- if (ret) {
- DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
- smb_get_krb5_error_message(context, ret, mem_ctx)));
- talloc_free(pac_data);
- return ret;
- }
-
- /* And push it out again, this time to the world. This relies on determanistic pointer values */
- nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
- (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
- talloc_free(pac_data);
- return EINVAL;
- }
-
- *pac = tmp_blob;
-
+ ret = kerberos_encode_pac(mem_ctx,
+ pac_data,
+ context,
+ krbtgt_keyblock,
+ service_keyblock,
+ pac);
talloc_free(pac_data);
return ret;
}