The branch, v3-6-test has been updated via f07f3d5 Fix 3.6 headers via ad8415c s3-gse: Use gss_get_name_attribute to fetch the pac from 3db7254 WHATSNEW: Start 3.6.0rc1 release notes.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test - Log ----------------------------------------------------------------- commit f07f3d5d11b57321dc0616b88afc78199a59e2d8 Author: Simo Sorce <i...@samba.org> Date: Fri May 13 16:36:42 2011 -0400 Fix 3.6 headers commit ad8415cb8a7bbd1f653eecce1aa2b88242bcc9e5 Author: Simo Sorce <i...@samba.org> Date: Mon May 9 11:33:41 2011 -0400 s3-gse: Use gss_get_name_attribute to fetch the pac This is the only way to be sure the pac signatures are correct. It requires a fairly new version of MIT Kerberos, but that should be fine, it is new functionality in 3.6 anyways. ----------------------------------------------------------------------- Summary of changes: source3/configure.in | 1 + source3/include/proto.h | 28 +------------- source3/lib/netapi/netapi_private.h | 2 + source3/librpc/crypto/gse.c | 74 +++++++++++++++++++++++------------ source3/librpc/crypto/gse.h | 3 +- source3/librpc/rpc/dcerpc_ep.c | 1 + source3/rpc_client/cli_winreg_int.h | 1 + source3/rpc_server/dcesrv_gssapi.c | 42 +------------------- source3/rpc_server/rpc_ncacn_np.h | 2 + source3/smbd/lanman.c | 1 + 10 files changed, 61 insertions(+), 94 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/configure.in b/source3/configure.in index d8c59b6..72568d8 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -3860,6 +3860,7 @@ if test x"$with_ads_support" != x"no"; then AC_CHECK_FUNC_EXT(krb5_get_credentials_for_user, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_get_host_realm, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_free_host_realm, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(gss_get_name_attribute, $KRB5_LIBS) # MIT krb5 1.8 does not expose this call (yet) AC_CHECK_DECLS(krb5_get_credentials_for_user, [], [], [#include <krb5.h>]) diff --git a/source3/include/proto.h b/source3/include/proto.h index 5f0e878..6c76029 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2667,33 +2667,6 @@ const struct ndr_interface_table *get_iface_from_syntax( const char *get_pipe_name_from_syntax(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax); -/* The following definitions come from rpc_server/rpc_ncacn_np.c */ -struct auth_serversupplied_info; -struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax, - struct client_address *client_id, - const struct auth_serversupplied_info *session_info, - struct messaging_context *msg_ctx); -struct dcerpc_binding_handle; -NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx, - const struct ndr_interface_table *ndr_table, - struct client_address *client_id, - const struct auth_serversupplied_info *session_info, - struct messaging_context *msg_ctx, - struct dcerpc_binding_handle **binding_handle); -NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *abstract_syntax, - const struct auth_serversupplied_info *serversupplied_info, - struct client_address *client_id, - struct messaging_context *msg_ctx, - struct rpc_pipe_client **presult); -NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx, - const struct ndr_syntax_id *syntax, - const struct auth_serversupplied_info *session_info, - struct client_address *client_id, - struct messaging_context *msg_ctx, - struct rpc_pipe_client **cli_pipe); - /* The following definitions come from rpc_client/cli_pipe_schannel.c */ NTSTATUS get_schannel_session_key(struct cli_state *cli, @@ -2703,6 +2676,7 @@ NTSTATUS get_schannel_session_key(struct cli_state *cli, /* The following definitions come from rpc_server/rpc_handles.c */ +struct pipes_struct; size_t num_pipe_handles(struct pipes_struct *p); bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *syntax); bool create_policy_hnd(struct pipes_struct *p, struct policy_handle *hnd, void *data_ptr); diff --git a/source3/lib/netapi/netapi_private.h b/source3/lib/netapi/netapi_private.h index 7559c61..349287b 100644 --- a/source3/lib/netapi/netapi_private.h +++ b/source3/lib/netapi/netapi_private.h @@ -29,6 +29,8 @@ } \ return fn ## _r(ctx, r); +struct dcerpc_binding_handle; + struct libnetapi_private_ctx { struct { const char *domain_name; diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c index 064ccda..335dc1c 100644 --- a/source3/librpc/crypto/gse.c +++ b/source3/librpc/crypto/gse.c @@ -22,7 +22,10 @@ #include "includes.h" #include "gse.h" -#if defined(HAVE_KRB5) && defined(HAVE_GSSAPI_GSSAPI_EXT_H) && defined(HAVE_GSS_WRAP_IOV) +#if defined(HAVE_KRB5) \ + && defined(HAVE_GSSAPI_GSSAPI_EXT_H) \ + && defined(HAVE_GSS_WRAP_IOV) \ + && defined(HAVE_GSS_GET_NAME_ATTRIBUTE) #include "smb_krb5.h" #include "gse_krb5.h" @@ -681,42 +684,62 @@ NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx, return NT_STATUS_OK; } -NTSTATUS gse_get_authtime(struct gse_context *gse_ctx, time_t *authtime) +NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx, + TALLOC_CTX *mem_ctx, DATA_BLOB *pac_blob) { OM_uint32 gss_min, gss_maj; - gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; - int32_t tkttime; + gss_buffer_desc pac_buffer; + gss_buffer_desc pac_display_buffer; + gss_buffer_desc pac_name = { + .value = discard_const_p(char, "urn:mspac:"), + .length = sizeof("urn:mspac:") - 1 + }; + int more = -1; + int authenticated = false; + int complete = false; + NTSTATUS status; if (!gse_ctx->authenticated) { return NT_STATUS_ACCESS_DENIED; } - gss_maj = gss_inquire_sec_context_by_oid( - &gss_min, gse_ctx->gss_ctx, - &gse_authtime_oid, &set); - if (gss_maj) { - DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n", - gse_errstr(talloc_tos(), gss_maj, gss_min))); - return NT_STATUS_NOT_FOUND; - } + gss_maj = gss_get_name_attribute(&gss_min, + gse_ctx->client_name, &pac_name, + &authenticated, &complete, + &pac_buffer, &pac_display_buffer, + &more); - if ((set == GSS_C_NO_BUFFER_SET) || (set->count != 1) != 0) { - DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown " - "data in results.\n")); - return NT_STATUS_INTERNAL_ERROR; + if (gss_maj != 0) { + DEBUG(0, ("obtaining PAC via GSSAPI gss_get_name_attribute " + "failed: %s\n", + gse_errstr(mem_ctx, gss_maj, gss_min))); + return NT_STATUS_ACCESS_DENIED; } - if (set->elements[0].length != sizeof(int32_t)) { - DEBUG(0, ("Invalid authtime size!\n")); - return NT_STATUS_INTERNAL_ERROR; - } + if (authenticated && complete) { + /* The PAC blob is returned directly */ + *pac_blob = data_blob_talloc(mem_ctx, + pac_buffer.value, + pac_buffer.length); + if (!pac_blob->data) { + status = NT_STATUS_NO_MEMORY; + } else { + status = NT_STATUS_OK; + } - tkttime = *((int32_t *)set->elements[0].value); + gss_maj = gss_release_buffer(&gss_min, &pac_buffer); + gss_maj = gss_release_buffer(&gss_min, &pac_display_buffer); - gss_maj = gss_release_buffer_set(&gss_min, &set); + return status; + } - *authtime = (time_t)tkttime; - return NT_STATUS_OK; + DEBUG(0, ("obtaining PAC via GSSAPI failed: authenticated: %s, " + "complete: %s, more: %s\n", + authenticated ? "true" : "false", + complete ? "true" : "false", + more ? "true" : "false")); + + return NT_STATUS_ACCESS_DENIED; } size_t gse_get_signature_length(struct gse_context *gse_ctx, @@ -972,7 +995,8 @@ NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx, return NT_STATUS_NOT_IMPLEMENTED; } -NTSTATUS gse_get_authtime(struct gse_context *gse_ctx, time_t *authtime) +NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx, + TALLOC_CTX *mem_ctx, DATA_BLOB *pac) { return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/source3/librpc/crypto/gse.h b/source3/librpc/crypto/gse.h index a6d9a35..d9e4a82 100644 --- a/source3/librpc/crypto/gse.h +++ b/source3/librpc/crypto/gse.h @@ -57,7 +57,8 @@ NTSTATUS gse_get_client_name(struct gse_context *gse_ctx, TALLOC_CTX *mem_ctx, char **client_name); NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx, TALLOC_CTX *mem_ctx, DATA_BLOB *pac); -NTSTATUS gse_get_authtime(struct gse_context *gse_ctx, time_t *authtime); +NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx, + TALLOC_CTX *mem_ctx, DATA_BLOB *pac); size_t gse_get_signature_length(struct gse_context *gse_ctx, int seal, size_t payload_size); diff --git a/source3/librpc/rpc/dcerpc_ep.c b/source3/librpc/rpc/dcerpc_ep.c index 76f7e91..5ed7185 100644 --- a/source3/librpc/rpc/dcerpc_ep.c +++ b/source3/librpc/rpc/dcerpc_ep.c @@ -23,6 +23,7 @@ #include "../librpc/gen_ndr/ndr_epmapper_c.h" #include "rpc_client/cli_pipe.h" #include "auth.h" +#include "rpc_server/rpc_ncacn_np.h" #define EPM_MAX_ANNOTATION_SIZE 64 diff --git a/source3/rpc_client/cli_winreg_int.h b/source3/rpc_client/cli_winreg_int.h index f175c17..9eac462 100644 --- a/source3/rpc_client/cli_winreg_int.h +++ b/source3/rpc_client/cli_winreg_int.h @@ -22,6 +22,7 @@ #ifndef CLI_WINREG_INT_H #define CLI_WINREG_INT_H +struct dcerpc_binding_handle; struct auth_serversupplied_info; /** diff --git a/source3/rpc_server/dcesrv_gssapi.c b/source3/rpc_server/dcesrv_gssapi.c index f60f6ce..25d85a6 100644 --- a/source3/rpc_server/dcesrv_gssapi.c +++ b/source3/rpc_server/dcesrv_gssapi.c @@ -106,11 +106,8 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx, { TALLOC_CTX *tmp_ctx; DATA_BLOB auth_data; - time_t tgs_authtime; - NTTIME tgs_authtime_nttime; DATA_BLOB pac; struct PAC_DATA *pac_data; - struct PAC_LOGON_NAME *logon_name = NULL; struct PAC_LOGON_INFO *logon_info = NULL; enum ndr_err_code ndr_err; unsigned int i; @@ -122,14 +119,13 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx, char *username; struct passwd *pw; NTSTATUS status; - bool bret; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } - status = gse_get_authz_data(gse_ctx, tmp_ctx, &auth_data); + status = gse_get_pac_blob(gse_ctx, tmp_ctx, &pac); if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { /* TODO: Fetch user by principal name ? */ status = NT_STATUS_ACCESS_DENIED; @@ -139,24 +135,6 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx, goto done; } - bret = unwrap_pac(tmp_ctx, &auth_data, &pac); - if (!bret) { - DEBUG(1, ("Failed to unwrap PAC\n")); - status = NT_STATUS_ACCESS_DENIED; - goto done; - } - - status = gse_get_client_name(gse_ctx, tmp_ctx, &princ_name); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - status = gse_get_authtime(gse_ctx, &tgs_authtime); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); - pac_data = talloc_zero(tmp_ctx, struct PAC_DATA); if (!pac_data) { status = NT_STATUS_NO_MEMORY; @@ -182,9 +160,6 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx, } logon_info = data_buf->info->logon_info.info; break; - case PAC_TYPE_LOGON_NAME: - logon_name = &data_buf->info->logon_name; - break; default: break; } @@ -194,21 +169,6 @@ NTSTATUS gssapi_server_get_user_info(struct gse_context *gse_ctx, status = NT_STATUS_NOT_FOUND; goto done; } - if (!logon_name) { - DEBUG(1, ("Invalid PAC data, missing logon info!\n")); - status = NT_STATUS_NOT_FOUND; - goto done; - } - - /* check time */ - if (tgs_authtime_nttime != logon_name->logon_time) { - DEBUG(1, ("Logon time mismatch between ticket and PAC!\n" - "PAC Time = %s | Ticket Time = %s\n", - nt_time_string(tmp_ctx, logon_name->logon_time), - nt_time_string(tmp_ctx, tgs_authtime_nttime))); - status = NT_STATUS_ACCESS_DENIED; - goto done; - } /* TODO: Should we check princ_name against account_name in * logon_name ? Are they supposed to be identical, or can an diff --git a/source3/rpc_server/rpc_ncacn_np.h b/source3/rpc_server/rpc_ncacn_np.h index a702e87..08b4788 100644 --- a/source3/rpc_server/rpc_ncacn_np.h +++ b/source3/rpc_server/rpc_ncacn_np.h @@ -20,6 +20,8 @@ #ifndef _RPC_NCACN_NP_H_ #define _RPC_NCACN_NP_H_ +struct dcerpc_binding_handle; + struct np_proxy_state { uint16_t file_type; uint16_t device_state; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 4803b40..74cfe31 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -42,6 +42,7 @@ #include "printing.h" #include "passdb/machine_sid.h" #include "auth.h" +#include "rpc_server/rpc_ncacn_np.h" #ifdef CHECK_TYPES #undef CHECK_TYPES -- Samba Shared Repository