diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-07-04 02:36:16 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:19:09 -0500 |
commit | dbd2688c9042faaa44f4d89068a8351523233875 (patch) | |
tree | 31cc633ae8f0f6a2437b3f726455548d9a6a051e /source4/auth | |
parent | 06348629b921adb6262e0f3d9a9c244568e2a78f (diff) | |
download | samba-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/auth')
-rw-r--r-- | source4/auth/auth_anonymous.c | 65 | ||||
-rw-r--r-- | source4/auth/auth_util.c | 68 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos.h | 2 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_pac.c | 110 |
4 files changed, 142 insertions, 103 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; } |