summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-07-04 02:36:16 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:19:09 -0500
commitdbd2688c9042faaa44f4d89068a8351523233875 (patch)
tree31cc633ae8f0f6a2437b3f726455548d9a6a051e /source4
parent06348629b921adb6262e0f3d9a9c244568e2a78f (diff)
downloadsamba-dbd2688c9042faaa44f4d89068a8351523233875.tar.gz
samba-dbd2688c9042faaa44f4d89068a8351523233875.tar.bz2
samba-dbd2688c9042faaa44f4d89068a8351523233875.zip
r8110: More PAC work. I still can't get WinXP to accept the PAC, but we are
much closer. This changes PIDL to allow a subcontext to have a pad8 flag, saying to pad behind to an 8 byte boundary. This is the only way I can explain the 4 trainling zeros in the signature struct. Far more importantly, the PAC code is now under self-test, both in creating/parsing our own PAC, but also a PAC from my win2k3 server. This required changing auth_anonymous, because I wanted to reuse the anonymous 'server_info' generation code. I'm still having trouble with PIDL, particulary as surrounds value(), but I'll follow up on the list. Andrew Bartlett (This used to be commit 50a54bf4e9bf04d2a8e0aebb3482a2ff655c8bbb)
Diffstat (limited to 'source4')
-rw-r--r--source4/auth/auth_anonymous.c65
-rw-r--r--source4/auth/auth_util.c68
-rw-r--r--source4/auth/kerberos/kerberos.h2
-rw-r--r--source4/auth/kerberos/kerberos_pac.c110
-rw-r--r--source4/build/pidl/ndr.pm3
-rw-r--r--source4/build/pidl/ndr_parser.pm6
-rw-r--r--source4/build/pidl/validator.pm1
-rw-r--r--source4/kdc/pac-glue.c12
-rw-r--r--source4/librpc/idl/krb5pac.idl12
-rw-r--r--source4/torture/auth/pac.c253
-rw-r--r--source4/torture/config.mk5
-rw-r--r--source4/torture/torture.c1
12 files changed, 423 insertions, 115 deletions
diff --git a/source4/auth/auth_anonymous.c b/source4/auth/auth_anonymous.c
index 4e78e77cc3..4325550413 100644
--- a/source4/auth/auth_anonymous.c
+++ b/source4/auth/auth_anonymous.c
@@ -37,74 +37,11 @@ static NTSTATUS anonymous_check_password(struct auth_method_context *ctx,
const struct auth_usersupplied_info *user_info,
struct auth_serversupplied_info **_server_info)
{
- struct auth_serversupplied_info *server_info;
-
if (user_info->account_name && *user_info->account_name) {
return NT_STATUS_NOT_IMPLEMENTED;
}
- server_info = talloc(mem_ctx, struct auth_serversupplied_info);
- NT_STATUS_HAVE_NO_MEMORY(server_info);
-
- server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS);
- NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
-
- /* is this correct? */
- server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS);
- NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
-
- server_info->n_domain_groups = 0;
- server_info->domain_groups = NULL;
-
- /* annoying, but the Anonymous really does have a session key,
- and it is all zeros! */
- server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
- NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
-
- server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
- NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
-
- data_blob_clear(&server_info->user_session_key);
- data_blob_clear(&server_info->lm_session_key);
-
- server_info->account_name = talloc_strdup(server_info, "ANONYMOUS LOGON");
- NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
-
- server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
- NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
-
- server_info->full_name = talloc_strdup(server_info, "Anonymous Logon");
- NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
-
- server_info->logon_script = talloc_strdup(server_info, "");
- NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
-
- server_info->profile_path = talloc_strdup(server_info, "");
- NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
-
- server_info->home_directory = talloc_strdup(server_info, "");
- NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
-
- server_info->home_drive = talloc_strdup(server_info, "");
- NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
-
- server_info->last_logon = 0;
- server_info->last_logoff = 0;
- server_info->acct_expiry = 0;
- server_info->last_password_change = 0;
- server_info->allow_password_change = 0;
- server_info->force_password_change = 0;
-
- server_info->logon_count = 0;
- server_info->bad_password_count = 0;
-
- server_info->acct_flags = ACB_NORMAL;
-
- server_info->authenticated = False;
-
- *_server_info = server_info;
-
- return NT_STATUS_OK;
+ return auth_anonymous_server_info(mem_ctx, _server_info);
}
static struct auth_operations anonymous_auth_ops = {
diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c
index 8c5bd4f057..2b9b0c25c2 100644
--- a/source4/auth/auth_util.c
+++ b/source4/auth/auth_util.c
@@ -425,6 +425,74 @@ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+
+NTSTATUS auth_anonymous_server_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **_server_info)
+{
+ struct auth_serversupplied_info *server_info;
+ server_info = talloc(mem_ctx, struct auth_serversupplied_info);
+ NT_STATUS_HAVE_NO_MEMORY(server_info);
+
+ server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_ANONYMOUS);
+ NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid);
+
+ /* is this correct? */
+ server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_GUESTS);
+ NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid);
+
+ server_info->n_domain_groups = 0;
+ server_info->domain_groups = NULL;
+
+ /* annoying, but the Anonymous really does have a session key,
+ and it is all zeros! */
+ server_info->user_session_key = data_blob_talloc(server_info, NULL, 16);
+ NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data);
+
+ server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16);
+ NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
+
+ data_blob_clear(&server_info->user_session_key);
+ data_blob_clear(&server_info->lm_session_key);
+
+ server_info->account_name = talloc_strdup(server_info, "ANONYMOUS LOGON");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->account_name);
+
+ server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name);
+
+ server_info->full_name = talloc_strdup(server_info, "Anonymous Logon");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
+
+ server_info->logon_script = talloc_strdup(server_info, "");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
+
+ server_info->profile_path = talloc_strdup(server_info, "");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
+
+ server_info->home_directory = talloc_strdup(server_info, "");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
+
+ server_info->home_drive = talloc_strdup(server_info, "");
+ NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
+
+ server_info->last_logon = 0;
+ server_info->last_logoff = 0;
+ server_info->acct_expiry = 0;
+ server_info->last_password_change = 0;
+ server_info->allow_password_change = 0;
+ server_info->force_password_change = 0;
+
+ server_info->logon_count = 0;
+ server_info->bad_password_count = 0;
+
+ server_info->acct_flags = ACB_NORMAL;
+
+ server_info->authenticated = False;
+
+ *_server_info = server_info;
+
+ return NT_STATUS_OK;
+}
+
NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
struct auth_serversupplied_info *server_info,
struct auth_session_info **_session_info)
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index 2fc000fd0d..a7c370a1e5 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -138,6 +138,6 @@ krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
krb5_context context,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *server_keyblock,
- krb5_data *pac);
+ DATA_BLOB *pac);
#endif /* HAVE_KRB5 */
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index fb8755c0b8..312013fdb9 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -1,9 +1,9 @@
/*
Unix SMB/CIFS implementation.
- Kerberos backend for GENSEC
+ Create and parse the krb5 PAC
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
Copyright (C) Andrew Tridgell 2001
Copyright (C) Luke Howard 2002-2003
Copyright (C) Stefan Metzmacher 2004-2005
@@ -92,8 +92,6 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
DATA_BLOB modified_pac_blob = data_blob_talloc(mem_ctx, blob.data, blob.length);
int i;
- file_save("/tmp/pac.in", blob.data, blob.length);
-
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)) {
@@ -156,8 +154,6 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
memset(&modified_pac_blob.data[modified_pac_blob.length - 44],
'\0', 16);
- file_save("/tmp/pac.in.blanked", modified_pac_blob.data, modified_pac_blob.length);
-
/* verify by service_key */
status = check_pac_checksum(mem_ctx,
modified_pac_blob, &srv_sig,
@@ -224,9 +220,10 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
krb5_context context,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *server_keyblock,
- krb5_data *pac)
+ DATA_BLOB *pac)
{
NTSTATUS nt_status;
+ DATA_BLOB zero_blob = data_blob(NULL, 0);
DATA_BLOB tmp_blob = data_blob(NULL, 0);
DATA_BLOB server_checksum_blob;
krb5_error_code ret;
@@ -234,11 +231,19 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
struct netr_SamBaseInfo *sam;
struct timeval tv = timeval_current();
+ enum {
+ PAC_BUF_LOGON_TYPE = 0,
+ PAC_BUF_LOGON_NAME = 1,
+ PAC_BUF_KDC_CHECKSUM = 2,
+ PAC_BUF_SRV_CHECKSUM = 3,
+ PAC_BUF_NUM_BUFFERS = 4
+ };
+
if (!pac_data) {
return ENOMEM;
}
- pac_data->num_buffers = 4;
+ pac_data->num_buffers = PAC_BUF_NUM_BUFFERS;
pac_data->version = 0;
pac_data->buffers = talloc_array(pac_data,
@@ -249,9 +254,10 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
talloc_free(pac_data);
return ENOMEM;
}
- pac_data->buffers[0].type = PAC_TYPE_LOGON_INFO;
- pac_data->buffers[0].info = talloc_zero(pac_data->buffers,
- union PAC_INFO);
+
+ pac_data->buffers[PAC_BUF_LOGON_TYPE].type = PAC_TYPE_LOGON_INFO;
+ pac_data->buffers[PAC_BUF_LOGON_TYPE].info = talloc_zero(pac_data->buffers,
+ union PAC_INFO);
nt_status = auth_convert_server_info_sambaseinfo(pac_data->buffers[0].info,
server_info, &sam);
@@ -261,81 +267,109 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
return EINVAL;
}
- pac_data->buffers[0].info->logon_info.info3.base = *sam;
-
- pac_data->buffers[1].type = PAC_TYPE_LOGON_NAME;
- pac_data->buffers[1].info = talloc_zero(pac_data->buffers,
+ pac_data->buffers[PAC_BUF_LOGON_TYPE].info->logon_info.info3.base = *sam;
+ pac_data->buffers[PAC_BUF_LOGON_TYPE].size
+ = ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_LOGON_TYPE].info,
+ pac_data->buffers[PAC_BUF_LOGON_TYPE].type,
+ 0);
+ pac_data->buffers[PAC_BUF_LOGON_TYPE]._pad = 0;
+
+ pac_data->buffers[PAC_BUF_LOGON_NAME].type = PAC_TYPE_LOGON_NAME;
+ pac_data->buffers[PAC_BUF_LOGON_NAME].info = talloc_zero(pac_data->buffers,
union PAC_INFO);
- pac_data->buffers[1].info->logon_name.account_name
+ pac_data->buffers[PAC_BUF_LOGON_NAME].info->logon_name.account_name
= server_info->account_name;
- pac_data->buffers[1].info->logon_name.logon_time
+ pac_data->buffers[PAC_BUF_LOGON_NAME].info->logon_name.logon_time
= timeval_to_nttime(&tv);
+ pac_data->buffers[PAC_BUF_LOGON_NAME].size
+ = ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_LOGON_NAME].info,
+ pac_data->buffers[PAC_BUF_LOGON_NAME].type,
+ 0);
+ pac_data->buffers[PAC_BUF_LOGON_NAME]._pad = 0;
- pac_data->buffers[2].type = PAC_TYPE_KDC_CHECKSUM;
- pac_data->buffers[2].info = talloc_zero(pac_data->buffers,
- union PAC_INFO);
- pac_data->buffers[3].type = PAC_TYPE_SRV_CHECKSUM;
- pac_data->buffers[3].info = talloc_zero(pac_data->buffers,
+ pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
+ pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = talloc_zero(pac_data->buffers,
union PAC_INFO);
-
/* First, just get the keytypes filled in (and lengths right, eventually) */
- ret = make_pac_checksum(mem_ctx, tmp_blob, &pac_data->buffers[2].info->srv_cksum,
+ ret = make_pac_checksum(mem_ctx, zero_blob,
+ &pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info->kdc_cksum,
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, tmp_blob, &pac_data->buffers[3].info->srv_cksum,
+ pac_data->buffers[PAC_BUF_KDC_CHECKSUM].size
+ = ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info,
+ pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type,
+ 0);
+ pac_data->buffers[PAC_BUF_KDC_CHECKSUM]._pad = 0;
+
+
+ pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
+ pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = talloc_zero(pac_data->buffers,
+ union PAC_INFO);
+ ret = make_pac_checksum(mem_ctx, zero_blob,
+ &pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info->srv_cksum,
context, server_keyblock);
if (ret) {
- DEBUG(2, ("making PAC checksum failed: %s\n",
+ DEBUG(2, ("making server PAC checksum failed: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
talloc_free(pac_data);
return ret;
}
+ pac_data->buffers[PAC_BUF_SRV_CHECKSUM].size
+ = ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info,
+ pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type,
+ 0);
+ pac_data->buffers[PAC_BUF_SRV_CHECKSUM]._pad = 0;
+
/* But wipe out the actual signatures */
- ZERO_STRUCT(pac_data->buffers[2].info->kdc_cksum.signature);
- ZERO_STRUCT(pac_data->buffers[3].info->srv_cksum.signature);
+ ZERO_STRUCT(pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info->kdc_cksum.signature);
+ ZERO_STRUCT(pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info->srv_cksum.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 push failed: %s\n", nt_errstr(nt_status)));
+ DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
talloc_free(pac_data);
return EINVAL;
}
- file_save("/tmp/pac.out.blank", tmp_blob.data, tmp_blob.length);
-
/* Then sign the result of the previous push, where the sig was zero'ed out */
ret = make_pac_checksum(mem_ctx, tmp_blob, &pac_data->buffers[3].info->srv_cksum,
context, server_keyblock);
/* Push the Server checksum out */
- nt_status = ndr_push_struct_blob(&server_checksum_blob, mem_ctx, &pac_data->buffers[3].info->srv_cksum,
+ nt_status = ndr_push_struct_blob(&server_checksum_blob, mem_ctx,
+ &pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info->srv_cksum,
(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(1, ("PAC push failed: %s\n", nt_errstr(nt_status)));
+ DEBUG(1, ("PAC_SIGNATURE 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, server_checksum_blob, &pac_data->buffers[2].info->kdc_cksum,
+ ret = make_pac_checksum(mem_ctx, server_checksum_blob,
+ &pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info->kdc_cksum,
context, krbtgt_keyblock);
/* 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 push failed: %s\n", nt_errstr(nt_status)));
+ DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
talloc_free(pac_data);
return EINVAL;
}
- file_save("/tmp/pac.out.signed", tmp_blob.data, tmp_blob.length);
+ *pac = tmp_blob;
- ret = krb5_data_copy(pac, tmp_blob.data, tmp_blob.length);
-
talloc_free(pac_data);
return ret;
}
diff --git a/source4/build/pidl/ndr.pm b/source4/build/pidl/ndr.pm
index 2bf673b5e3..c4ff1d8a89 100644
--- a/source4/build/pidl/ndr.pm
+++ b/source4/build/pidl/ndr.pm
@@ -166,7 +166,8 @@ sub GetElementLevelTable($)
SUBCONTEXT_SIZE => $subsize,
IS_DEFERRED => $is_deferred,
COMPRESSION => util::has_property($e, "compression"),
- OBFUSCATION => util::has_property($e, "obfuscation")
+ OBFUSCATION => util::has_property($e, "obfuscation"),
+ PAD8 => util::has_property($e, "pad8")
});
}
diff --git a/source4/build/pidl/ndr_parser.pm b/source4/build/pidl/ndr_parser.pm
index ba6b9d58da..48e243aa0c 100644
--- a/source4/build/pidl/ndr_parser.pm
+++ b/source4/build/pidl/ndr_parser.pm
@@ -452,6 +452,9 @@ sub ParseSubcontextPushEnd($$$$)
pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $l->{HEADER_SIZE}, $subcontext_size, $ndr));";
pidl "NDR_CHECK(ndr_push_bytes(ndr, $ndr->data, $ndr->offset));";
+ if (defined $l->{PAD8}) {
+ pidl "NDR_CHECK(ndr_push_align(ndr, 8));";
+ }
deindent;
pidl "}";
}
@@ -501,6 +504,9 @@ sub ParseSubcontextPullEnd($$$)
$advance = "$ndr->offset";
}
pidl "NDR_CHECK(ndr_pull_advance(ndr, $advance));";
+ if (defined $l->{PAD8}) {
+ pidl "NDR_CHECK(ndr_pull_align(ndr, 8));";
+ }
deindent;
pidl "}";
}
diff --git a/source4/build/pidl/validator.pm b/source4/build/pidl/validator.pm
index fbf7993b20..f1677d1ae7 100644
--- a/source4/build/pidl/validator.pm
+++ b/source4/build/pidl/validator.pm
@@ -106,6 +106,7 @@ my %property_list = (
"default" => ["ELEMENT"],
# subcontext
+ "pad8" => ["ELEMENT"],
"subcontext" => ["ELEMENT"],
"subcontext_size" => ["ELEMENT"],
"compression" => ["ELEMENT"],
diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
index 52685083bd..c986d60fdf 100644
--- a/source4/kdc/pac-glue.c
+++ b/source4/kdc/pac-glue.c
@@ -37,6 +37,7 @@
struct auth_serversupplied_info *server_info;
char *username, *p;
const char *realm;
+ DATA_BLOB tmp_blob;
TALLOC_CTX *mem_ctx = talloc_named(config, 0, "samba_get_pac context");
if (!mem_ctx) {
return ENOMEM;
@@ -73,9 +74,16 @@
context,
krbtgt_keyblock,
server_keyblock,
- pac);
+ &tmp_blob);
+ if (ret) {
+ DEBUG(1, ("PAC encoding failed: %s\n",
+ smb_get_krb5_error_message(context, ret, mem_ctx)));
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ ret = krb5_data_copy(pac, tmp_blob.data, tmp_blob.length);
talloc_free(mem_ctx);
-
return ret;
}
diff --git a/source4/librpc/idl/krb5pac.idl b/source4/librpc/idl/krb5pac.idl
index 71acfd79bd..4de5453478 100644
--- a/source4/librpc/idl/krb5pac.idl
+++ b/source4/librpc/idl/krb5pac.idl
@@ -16,13 +16,11 @@ interface krb5pac
typedef struct {
NTTIME logon_time;
[flag(STR_SIZE2|STR_NOTERM|STR_BYTESIZE)] string account_name;
- [value(0)] uint32 _pad;
} PAC_LOGON_NAME;
typedef [public,flag(NDR_PAHEX)] struct {
uint32 type;
uint8 signature[16];
- [value(0)] uint32 _pad;
} PAC_SIGNATURE_DATA;
typedef struct {
@@ -37,7 +35,7 @@ interface krb5pac
const uint8 PAC_TYPE_KDC_CHECKSUM = 7;
const uint8 PAC_TYPE_LOGON_NAME = 10;
- typedef [nodiscriminant,gensize,flag(NDR_ALIGN8)] union {
+ typedef [nodiscriminant,gensize] union {
[case(PAC_TYPE_LOGON_INFO)] PAC_LOGON_INFO logon_info;
[case(PAC_TYPE_SRV_CHECKSUM)] PAC_SIGNATURE_DATA srv_cksum;
[case(PAC_TYPE_KDC_CHECKSUM)] PAC_SIGNATURE_DATA kdc_cksum;
@@ -46,12 +44,12 @@ interface krb5pac
typedef struct {
uint32 type;
- [value(ndr_size_PAC_INFO(info,type,ndr->flags))] uint32 size;
- [relative,switch_is(type)] PAC_INFO *info;
- [value(0)] uint32 _pad; /* Top half of a 64 bit pointer? */
+ uint32 size;
+ [relative,switch_is(type),subcontext(0),subcontext_size(size),pad8] PAC_INFO *info;
+ uint32 _pad; /* Top half of a 64 bit pointer? */
} PAC_BUFFER;
- typedef [public,flag(NDR_ALIGN8)] struct {
+ typedef [public] struct {
uint32 num_buffers;
uint32 version;
PAC_BUFFER buffers[num_buffers];
diff --git a/source4/torture/auth/pac.c b/source4/torture/auth/pac.c
new file mode 100644
index 0000000000..79cae5cbea
--- /dev/null
+++ b/source4/torture/auth/pac.c
@@ -0,0 +1,253 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Validate the krb5 pac generation routines
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/kerberos.h"
+#include "system/time.h"
+#include "system/network.h"
+#include "auth/auth.h"
+#include "auth/kerberos/kerberos.h"
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "auth/auth.h"
+
+static BOOL torture_pac_self_check(void)
+{
+ NTSTATUS nt_status;
+ TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC self check");
+ DATA_BLOB tmp_blob;
+ struct PAC_LOGON_INFO *pac_info;
+
+ /* Generate a nice, arbitary keyblock */
+ uint8_t server_bytes[16];
+ uint8_t krbtgt_bytes[16];
+ krb5_keyblock server_keyblock;
+ krb5_keyblock krbtgt_keyblock;
+
+ krb5_error_code ret;
+
+ struct smb_krb5_context *smb_krb5_context;
+
+ struct auth_serversupplied_info *server_info;
+
+ ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
+
+ if (ret) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ generate_random_buffer(server_bytes, 16);
+ generate_random_buffer(krbtgt_bytes, 16);
+
+ ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
+ ENCTYPE_ARCFOUR_HMAC,
+ server_bytes, sizeof(server_bytes),
+ &server_keyblock);
+ if (ret) {
+ DEBUG(1, ("Server Keyblock encoding failed: %s\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
+ ENCTYPE_ARCFOUR_HMAC,
+ krbtgt_bytes, sizeof(krbtgt_bytes),
+ &krbtgt_keyblock);
+ if (ret) {
+ DEBUG(1, ("KRBTGT Keyblock encoding failed: %s\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &server_keyblock);
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ /* We need an input, and this one requires no underlying database */
+ nt_status = auth_anonymous_server_info(mem_ctx, &server_info);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &server_keyblock);
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &krbtgt_keyblock);
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ /* OK, go ahead and make a PAC */
+ ret = kerberos_encode_pac(mem_ctx, server_info,
+ smb_krb5_context->krb5_context,
+ &krbtgt_keyblock,
+ &server_keyblock,
+ &tmp_blob);
+
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &krbtgt_keyblock);
+
+ if (ret) {
+ DEBUG(1, ("PAC encoding failed: %s\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &server_keyblock);
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ /* Now check that we can read it back */
+ nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
+ tmp_blob,
+ smb_krb5_context,
+ &server_keyblock);
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &server_keyblock);
+ if (ret) {
+ DEBUG(1, ("PAC decoding failed: %s\n",
+ nt_errstr(nt_status)));
+
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ talloc_free(mem_ctx);
+ return True;
+}
+
+
+/* This is the PAC generated on my test network, by my test Win2k3 server.
+ -- abartlet 2005-07-04
+ */
+
+static const char saved_pac[] = {
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
+ 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb,
+ 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59,
+ 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00,
+ 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00,
+ 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00,
+ 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+ 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00,
+ 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00,
+ 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00,
+ 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00,
+ 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc,
+ 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00,
+ 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00,
+ 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a,
+ 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe,
+ 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00
+};
+
+/* Check with a known 'well formed' PAC, from my test server */
+static BOOL torture_pac_saved_check(void)
+{
+ NTSTATUS nt_status;
+ TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
+ DATA_BLOB tmp_blob;
+ struct PAC_LOGON_INFO *pac_info;
+ krb5_keyblock server_keyblock;
+ uint8_t server_bytes[16];
+
+ krb5_error_code ret;
+
+ struct smb_krb5_context *smb_krb5_context;
+
+ ret = smb_krb5_init_context(mem_ctx, &smb_krb5_context);
+
+ if (ret) {
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ /* The machine trust account in use when the above PAC
+ was generated. It used arcfour-hmac-md5, so this is easy */
+ E_md4hash("iqvwmii8CuEkyY", server_bytes);
+
+ ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
+ ENCTYPE_ARCFOUR_HMAC,
+ server_bytes, sizeof(server_bytes),
+ &server_keyblock);
+ if (ret) {
+ DEBUG(1, ("Server Keyblock encoding failed: %s\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+
+ talloc_free(mem_ctx);
+ return False;
+ }
+
+ tmp_blob = data_blob_const(saved_pac, sizeof(saved_pac));
+
+ /* Decode and verify the signaure on the PAC */
+ nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
+ tmp_blob,
+ smb_krb5_context,
+ &server_keyblock);
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &server_keyblock);
+ if (ret) {
+ DEBUG(1, ("PAC decoding failed: %s\n",
+ nt_errstr(nt_status)));
+
+ talloc_free(mem_ctx);
+ return False;
+ }
+ talloc_free(mem_ctx);
+ return True;
+}
+
+BOOL torture_pac(void)
+{
+ BOOL ret = True;
+ ret &= torture_pac_self_check();
+ ret &= torture_pac_saved_check();
+ return ret;
+}
diff --git a/source4/torture/config.mk b/source4/torture/config.mk
index 8144dcfe80..6b373f9650 100644
--- a/source4/torture/config.mk
+++ b/source4/torture/config.mk
@@ -129,9 +129,10 @@ REQUIRED_SUBSYSTEMS = \
# Start SUBSYSTEM TORTURE_AUTH
[SUBSYSTEM::TORTURE_AUTH]
ADD_OBJ_FILES = \
- torture/auth/ntlmssp.o
+ torture/auth/ntlmssp.o \
+ torture/auth/pac.o
REQUIRED_SUBSYSTEMS = \
- LIBSMB
+ LIBSMB GENSEC AUTH
# End SUBSYSTEM TORTURE_AUTH
#################################
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index c5ac873591..157233d43d 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -2317,6 +2317,7 @@ static struct {
{"LOCAL-BINDING", torture_local_binding_string, 0},
{"LOCAL-IDTREE", torture_local_idtree, 0},
{"LOCAL-SOCKET", torture_local_socket, 0},
+ {"LOCAL-PAC", torture_pac, 0},
/* COM (Component Object Model) testers */
{"COM-SIMPLE", torture_com_simple, 0 },