[SCM] Samba Shared Repository - branch v4-0-test updated -
release-4-0-0alpha5-427-gacfa87f
Andrew Bartlett
abartlet at samba.org
Thu Aug 28 07:29:15 GMT 2008
The branch, v4-0-test has been updated
via acfa87f3411a61bdd9066fbbba2bcfbe2a60cbbe (commit)
via 418b440a7b8cdb53035045f3981d47b078be6c1e (commit)
via 9db5a966fce0b71a0d2167b4aff70cc081abc1cc (commit)
from 0343987cf18c1287d98ae542d397ab1fab0a04b7 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test
- Log -----------------------------------------------------------------
commit acfa87f3411a61bdd9066fbbba2bcfbe2a60cbbe
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Aug 28 16:30:17 2008 +1000
Further rework the RPC-PAC test.
This would seem to match the documentation requirements for the PAC
verfication over NETLOGON, but I can't get Win2k3 to accept it so far.
Andrew Bartlett
commit 418b440a7b8cdb53035045f3981d47b078be6c1e
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Aug 28 16:28:47 2008 +1000
Heimdal provides Kerberos PAC parsing routines. Use them.
This uses Heimdal's PAC parsing code in the:
- LOCAL-PAC test
- gensec_gssapi server
- KDC (where is was already used, the support code refactored from here)
In addition, the service and KDC checksums are recorded in the struct
auth_serversupplied_info, allowing them to be extracted for validation
across NETLOGON.
Andrew Bartlett
commit 9db5a966fce0b71a0d2167b4aff70cc081abc1cc
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Aug 28 16:19:16 2008 +1000
Don't wipe the PAC checksums, the caller may actually need them.
-----------------------------------------------------------------------
Summary of changes:
source/auth/auth.h | 4 +
source/auth/gensec/gensec_gssapi.c | 129 +++++++++++------------------------
source/auth/kerberos/kerberos_pac.c | 123 +++++++++++++++++++++++++++++++++-
source/auth/session.c | 3 +
source/heimdal/lib/krb5/pac.c | 14 ----
source/kdc/pac-glue.c | 44 ++----------
source/librpc/idl/krb5pac.idl | 2 +-
source/torture/auth/pac.c | 69 ++++++++++++++++++-
source/torture/rpc/remote_pac.c | 49 ++++---------
9 files changed, 259 insertions(+), 178 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source/auth/auth.h b/source/auth/auth.h
index da8aac4..af9ed52 100644
--- a/source/auth/auth.h
+++ b/source/auth/auth.h
@@ -21,6 +21,8 @@
#ifndef _SAMBA_AUTH_H
#define _SAMBA_AUTH_H
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+
extern const char *user_attrs[];
union netr_Validation;
@@ -115,6 +117,8 @@ struct auth_serversupplied_info
uint32_t acct_flags;
bool authenticated;
+
+ struct PAC_SIGNATURE_DATA pac_srv_sig, pac_kdc_sig;
};
struct auth_method_context;
diff --git a/source/auth/gensec/gensec_gssapi.c b/source/auth/gensec/gensec_gssapi.c
index 2057625..1334e79 100644
--- a/source/auth/gensec/gensec_gssapi.c
+++ b/source/auth/gensec/gensec_gssapi.c
@@ -1221,14 +1221,8 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
struct auth_serversupplied_info *server_info = NULL;
struct auth_session_info *session_info = NULL;
- struct PAC_LOGON_INFO *logon_info;
OM_uint32 maj_stat, min_stat;
- gss_buffer_desc name_token;
gss_buffer_desc pac;
- krb5_keyblock *keyblock;
- time_t authtime;
- krb5_principal principal;
- char *principal_string;
DATA_BLOB pac_blob;
if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)
@@ -1241,28 +1235,6 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context");
NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
- maj_stat = gss_display_name (&min_stat,
- gensec_gssapi_state->client_name,
- &name_token,
- NULL);
- if (GSS_ERROR(maj_stat)) {
- DEBUG(1, ("GSS display_name failed: %s\n",
- gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
- talloc_free(mem_ctx);
- return NT_STATUS_FOOBAR;
- }
-
- principal_string = talloc_strndup(mem_ctx,
- (const char *)name_token.value,
- name_token.length);
-
- gss_release_buffer(&min_stat, &name_token);
-
- if (!principal_string) {
- talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
gensec_gssapi_state->gssapi_context,
KRB5_AUTHDATA_WIN2K_PAC,
@@ -1282,82 +1254,63 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
* kind...
*/
if (pac_blob.length) {
- krb5_error_code ret;
- union netr_Validation validation;
-
- maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
- gensec_gssapi_state->gssapi_context,
- &authtime);
-
- if (GSS_ERROR(maj_stat)) {
- DEBUG(1, ("gsskrb5_extract_authtime_from_sec_context: %s\n",
- gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+ nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
+ lp_iconv_convenience(gensec_security->lp_ctx),
+ pac_blob,
+ gensec_gssapi_state->smb_krb5_context->krb5_context,
+ &server_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
- return NT_STATUS_FOOBAR;
+ return nt_status;
}
+ } else {
+ gss_buffer_desc name_token;
+ char *principal_string;
- maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
- gensec_gssapi_state->gssapi_context,
- &keyblock);
-
+ maj_stat = gss_display_name (&min_stat,
+ gensec_gssapi_state->client_name,
+ &name_token,
+ NULL);
if (GSS_ERROR(maj_stat)) {
- DEBUG(1, ("gsskrb5_copy_service_keyblock failed: %s\n",
+ DEBUG(1, ("GSS display_name failed: %s\n",
gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
talloc_free(mem_ctx);
return NT_STATUS_FOOBAR;
- }
-
- ret = krb5_parse_name_flags(gensec_gssapi_state->smb_krb5_context->krb5_context,
- principal_string,
- KRB5_PRINCIPAL_PARSE_MUST_REALM,
- &principal);
- if (ret) {
- krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context,
- keyblock);
- talloc_free(mem_ctx);
- return NT_STATUS_INVALID_PARAMETER;
}
- /* decode and verify the pac */
- nt_status = kerberos_pac_logon_info(mem_ctx, lp_iconv_convenience(gensec_security->lp_ctx), &logon_info, pac_blob,
- gensec_gssapi_state->smb_krb5_context->krb5_context,
- NULL, keyblock, principal, authtime, NULL);
- krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal);
- krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context,
- keyblock);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- talloc_free(mem_ctx);
- return nt_status;
- }
- validation.sam3 = &logon_info->info3;
- nt_status = make_server_info_netlogon_validation(gensec_gssapi_state,
- NULL,
- 3, &validation,
- &server_info);
- if (!NT_STATUS_IS_OK(nt_status)) {
+ principal_string = talloc_strndup(mem_ctx,
+ (const char *)name_token.value,
+ name_token.length);
+
+ gss_release_buffer(&min_stat, &name_token);
+
+ if (!principal_string) {
talloc_free(mem_ctx);
- return nt_status;
+ return NT_STATUS_NO_MEMORY;
}
- } else if (!lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec", "require_pac", false)) {
- DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
- gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
- nt_status = sam_get_server_info_principal(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, principal_string,
- &server_info);
- if (!NT_STATUS_IS_OK(nt_status)) {
- talloc_free(mem_ctx);
- return nt_status;
+ if (!lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec", "require_pac", false)) {
+ DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
+ gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+ nt_status = sam_get_server_info_principal(mem_ctx, gensec_security->event_ctx,
+ gensec_security->lp_ctx, principal_string,
+ &server_info);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
+ } else {
+ DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
+ principal_string,
+ gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
+ return NT_STATUS_ACCESS_DENIED;
}
- } else {
- DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
- principal_string,
- gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
- return NT_STATUS_ACCESS_DENIED;
}
/* references the server_info into the session_info */
- nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, server_info, &session_info);
+ nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx,
+ gensec_security->lp_ctx, server_info, &session_info);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return nt_status;
diff --git a/source/auth/kerberos/kerberos_pac.c b/source/auth/kerberos/kerberos_pac.c
index e485f75..9ebace3 100644
--- a/source/auth/kerberos/kerberos_pac.c
+++ b/source/auth/kerberos/kerberos_pac.c
@@ -3,7 +3,7 @@
Create and parse the krb5 PAC
- Copyright (C) Andrew Bartlett <abartlet at samba.org> 2004-2005
+ Copyright (C) Andrew Bartlett <abartlet at samba.org> 2004-2005,2008
Copyright (C) Andrew Tridgell 2001
Copyright (C) Luke Howard 2002-2003
Copyright (C) Stefan Metzmacher 2004-2005
@@ -25,6 +25,7 @@
#include "includes.h"
#include "system/kerberos.h"
+#include "auth/auth.h"
#include "auth/kerberos/kerberos.h"
#include "librpc/gen_ndr/ndr_krb5pac.h"
#include "lib/ldb/include/ldb.h"
@@ -654,3 +655,123 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
return ret;
}
+krb5_error_code kerberos_pac_to_server_info(TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
+ krb5_pac pac,
+ krb5_context context,
+ struct auth_serversupplied_info **server_info)
+{
+ NTSTATUS nt_status;
+ enum ndr_err_code ndr_err;
+ krb5_error_code ret;
+
+ DATA_BLOB pac_logon_info_in, pac_srv_checksum_in, pac_kdc_checksum_in;
+ krb5_data k5pac_logon_info_in, k5pac_srv_checksum_in, k5pac_kdc_checksum_in;
+
+ union PAC_INFO info;
+ union netr_Validation validation;
+ struct auth_serversupplied_info *server_info_out;
+
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_LOGON_INFO, &k5pac_logon_info_in);
+ if (ret != 0) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ pac_logon_info_in = data_blob_const(k5pac_logon_info_in.data, k5pac_logon_info_in.length);
+
+ ndr_err = ndr_pull_union_blob(&pac_logon_info_in, tmp_ctx, iconv_convenience, &info,
+ PAC_TYPE_LOGON_INFO,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
+ krb5_data_free(&k5pac_logon_info_in);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
+ nt_status = ndr_map_error2ntstatus(ndr_err);
+ DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ /* Pull this right into the normal auth sysstem structures */
+ validation.sam3 = &info.logon_info.info->info3;
+ nt_status = make_server_info_netlogon_validation(mem_ctx,
+ "",
+ 3, &validation,
+ &server_info_out);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(tmp_ctx);
+ return EINVAL;
+ }
+
+ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_SRV_CHECKSUM, &k5pac_srv_checksum_in);
+ if (ret != 0) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ pac_srv_checksum_in = data_blob_const(k5pac_srv_checksum_in.data, k5pac_srv_checksum_in.length);
+
+ ndr_err = ndr_pull_struct_blob(&pac_srv_checksum_in, server_info_out,
+ iconv_convenience, &server_info_out->pac_srv_sig,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
+ krb5_data_free(&k5pac_srv_checksum_in);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ nt_status = ndr_map_error2ntstatus(ndr_err);
+ DEBUG(0,("can't parse the KDC signature: %s\n",
+ nt_errstr(nt_status)));
+ return EINVAL;
+ }
+
+ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_KDC_CHECKSUM, &k5pac_kdc_checksum_in);
+ if (ret != 0) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ pac_kdc_checksum_in = data_blob_const(k5pac_kdc_checksum_in.data, k5pac_kdc_checksum_in.length);
+
+ ndr_err = ndr_pull_struct_blob(&pac_kdc_checksum_in, server_info_out,
+ iconv_convenience, &server_info_out->pac_kdc_sig,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
+ krb5_data_free(&k5pac_kdc_checksum_in);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ nt_status = ndr_map_error2ntstatus(ndr_err);
+ DEBUG(0,("can't parse the KDC signature: %s\n",
+ nt_errstr(nt_status)));
+ return EINVAL;
+ }
+
+ *server_info = server_info_out;
+
+ return 0;
+}
+
+
+NTSTATUS kerberos_pac_blob_to_server_info(TALLOC_CTX *mem_ctx,
+ struct smb_iconv_convenience *iconv_convenience,
+ DATA_BLOB pac_blob,
+ krb5_context context,
+ struct auth_serversupplied_info **server_info)
+{
+ krb5_error_code ret;
+ krb5_pac pac;
+ ret = krb5_pac_parse(context,
+ pac_blob.data, pac_blob.length,
+ &pac);
+ if (ret) {
+ return map_nt_error_from_unix(ret);
+ }
+
+
+ ret = kerberos_pac_to_server_info(mem_ctx, iconv_convenience, pac, context, server_info);
+ krb5_pac_free(context, pac);
+ if (ret) {
+ return map_nt_error_from_unix(ret);
+ }
+ return NT_STATUS_OK;
+}
diff --git a/source/auth/session.c b/source/auth/session.c
index b254ee5..d75f179 100644
--- a/source/auth/session.c
+++ b/source/auth/session.c
@@ -333,6 +333,9 @@ _PUBLIC_ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data);
}
+ ZERO_STRUCT(server_info->pac_srv_sig);
+ ZERO_STRUCT(server_info->pac_kdc_sig);
+
*_server_info = server_info;
return NT_STATUS_OK;
}
diff --git a/source/heimdal/lib/krb5/pac.c b/source/heimdal/lib/krb5/pac.c
index ac7e3ed..9a145c4 100644
--- a/source/heimdal/lib/krb5/pac.c
+++ b/source/heimdal/lib/krb5/pac.c
@@ -324,20 +324,6 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p,
krb5_error_code ret;
uint32_t i;
- /*
- * Hide the checksums from external consumers
- */
-
- if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) {
- ret = krb5_data_alloc(data, 16);
- if (ret) {
- krb5_set_error_message(context, ret, "malloc: out of memory");
- return ret;
- }
- memset(data->data, 0, data->length);
- return 0;
- }
-
for (i = 0; i < p->pac->numbuffers; i++) {
size_t len = p->pac->buffers[i].buffersize;
size_t offset = p->pac->buffers[i].offset_lo;
diff --git a/source/kdc/pac-glue.c b/source/kdc/pac-glue.c
index bee271e..cbdbb86 100644
--- a/source/kdc/pac-glue.c
+++ b/source/kdc/pac-glue.c
@@ -153,18 +153,12 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
struct hdb_entry_ex *client,
struct hdb_entry_ex *server, krb5_pac *pac)
{
- NTSTATUS nt_status;
- enum ndr_err_code ndr_err;
krb5_error_code ret;
unsigned int userAccountControl;
struct hdb_ldb_private *private = talloc_get_type(server->ctx, struct hdb_ldb_private);
- krb5_data k5pac_in;
- DATA_BLOB pac_in;
- union PAC_INFO info;
- union netr_Validation validation;
struct auth_serversupplied_info *server_info_out;
TALLOC_CTX *mem_ctx = talloc_named(private, 0, "samba_get_pac context");
@@ -176,46 +170,22 @@ krb5_error_code samba_kdc_reget_pac(void *priv, krb5_context context,
/* The service account may be set not to want the PAC */
userAccountControl = ldb_msg_find_attr_as_uint(private->msg, "userAccountControl", 0);
if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
+ talloc_free(mem_ctx);
*pac = NULL;
return 0;
}
- ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &k5pac_in);
- if (ret != 0) {
- return ret;
- }
+ ret = kerberos_pac_to_server_info(mem_ctx, private->iconv_convenience,
+ *pac, context, &server_info_out);
- pac_in = data_blob_talloc(mem_ctx, k5pac_in.data, k5pac_in.length);
- krb5_data_free(&k5pac_in);
- if (!pac_in.data) {
- talloc_free(mem_ctx);
- return ENOMEM;
- }
-
- ndr_err = ndr_pull_union_blob(&pac_in, mem_ctx, private->iconv_convenience, &info,
- PAC_TYPE_LOGON_INFO,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || !info.logon_info.info) {
- nt_status = ndr_map_error2ntstatus(ndr_err);
- DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
- talloc_free(mem_ctx);
- return EINVAL;
- }
+ /* We will compleatly regenerate this pac */
+ krb5_pac_free(context, *pac);
- /* Pull this right into the normal auth sysstem structures */
- validation.sam3 = &info.logon_info.info->info3;
- nt_status = make_server_info_netlogon_validation(mem_ctx,
- "",
- 3, &validation,
- &server_info_out);
- if (!NT_STATUS_IS_OK(nt_status)) {
+ if (ret) {
talloc_free(mem_ctx);
- return ENOMEM;
+ return ret;
}
- /* We will compleatly regenerate this pac */
- krb5_pac_free(context, *pac);
-
ret = make_pac(context, mem_ctx, private->iconv_convenience, server_info_out, pac);
talloc_free(mem_ctx);
diff --git a/source/librpc/idl/krb5pac.idl b/source/librpc/idl/krb5pac.idl
index 07f747a..699f0b8 100644
--- a/source/librpc/idl/krb5pac.idl
+++ b/source/librpc/idl/krb5pac.idl
@@ -105,7 +105,7 @@ interface krb5pac
uint32 ChecksumLength;
uint32 SignatureType;
uint32 SignatureLength;
- [size_is(ChecksumLength),length_is(ChecksumLength)] uint8 *data;
+ [flag(NDR_REMAINING)] DATA_BLOB ChecksumAndSignature;
} PAC_Validate;
void decode_pac(
diff --git a/source/torture/auth/pac.c b/source/torture/auth/pac.c
index 4e51c66..42901f1 100644
--- a/source/torture/auth/pac.c
+++ b/source/torture/auth/pac.c
@@ -139,7 +139,7 @@ static bool torture_pac_self_check(struct torture_context *tctx)
dump_data(10,tmp_blob.data,tmp_blob.length);
- /* Now check that we can read it back */
+ /* Now check that we can read it back (using full decode and validate) */
nt_status = kerberos_decode_pac(mem_ctx,
lp_iconv_convenience(tctx->lp_ctx),
&pac_data,
@@ -163,7 +163,31 @@ static bool torture_pac_self_check(struct torture_context *tctx)
nt_errstr(nt_status)));
}
- /* Now check that we can read it back */
+ /* Now check we can read it back (using Heimdal's pac parsing) */
+ nt_status = kerberos_pac_blob_to_server_info(mem_ctx,
+ lp_iconv_convenience(tctx->lp_ctx),
+ tmp_blob,
+ smb_krb5_context->krb5_context,
+ &server_info_out);
+
+ if (!dom_sid_equal(server_info->account_sid,
+ server_info_out->account_sid)) {
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &krbtgt_keyblock);
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
+ &server_keyblock);
+ krb5_free_principal(smb_krb5_context->krb5_context,
--
Samba Shared Repository
More information about the samba-cvs
mailing list