summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth')
-rw-r--r--source4/auth/credentials/credentials_krb5.h4
-rw-r--r--source4/auth/gensec/gensec_gssapi.c127
-rw-r--r--source4/auth/gensec/gensec_krb5.c98
-rw-r--r--source4/auth/kerberos/kerberos.c4
-rw-r--r--source4/auth/kerberos/kerberos_pac.c6
-rw-r--r--source4/auth/kerberos/krb5_init_context.c32
-rw-r--r--source4/auth/kerberos/krb5_init_context.h5
7 files changed, 159 insertions, 117 deletions
diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h
index 2bd38af5c7..22c0f5abfe 100644
--- a/source4/auth/credentials/credentials_krb5.h
+++ b/source4/auth/credentials/credentials_krb5.h
@@ -21,9 +21,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-struct EncryptionKey;
-
-#include "heimdal/lib/gssapi/gssapi.h"
+#include "heimdal/lib/gssapi/gssapi/gssapi.h"
struct ccache_container;
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index ed407b623b..136962d892 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -24,7 +24,7 @@
#include "includes.h"
#include "system/kerberos.h"
-#include "heimdal/lib/gssapi/gssapi.h"
+#include "heimdal/lib/gssapi/gssapi/gssapi.h"
#include "auth/kerberos/kerberos.h"
#include "librpc/gen_ndr/krb5pac.h"
#include "auth/auth.h"
@@ -73,6 +73,7 @@ struct gensec_gssapi_state {
* layer... */
size_t max_wrap_buf_size;
+ int gss_exchange_count;
};
static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
@@ -133,12 +134,14 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
{
struct gensec_gssapi_state *gensec_gssapi_state;
krb5_error_code ret;
-
+ struct gsskrb5_send_to_kdc send_to_kdc;
+
gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
if (!gensec_gssapi_state) {
return NT_STATUS_NO_MEMORY;
}
+ gensec_gssapi_state->gss_exchange_count = 0;
gensec_gssapi_state->max_wrap_buf_size
= lp_parm_int(-1, "gensec_gssapi", "max wrap buf size", 65536);
@@ -186,10 +189,18 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
gensec_gssapi_state->gss_oid = gss_mech_krb5;
+ send_to_kdc.func = smb_krb5_send_and_recv_func;
+ send_to_kdc.ptr = gensec_security->event_ctx;
+
+ ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
+ if (ret) {
+ DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
ret = smb_krb5_init_context(gensec_gssapi_state,
&gensec_gssapi_state->smb_krb5_context);
if (ret) {
- DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
+ DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
error_message(ret)));
return NT_STATUS_INTERNAL_ERROR;
}
@@ -431,6 +442,8 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
}
+ gensec_gssapi_state->gss_exchange_count++;
+
if (maj_stat == GSS_S_COMPLETE) {
*out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
gss_release_buffer(&min_stat2, &output_token);
@@ -493,12 +506,14 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
/* garbage input, possibly from the auto-mech detection */
return NT_STATUS_INVALID_PARAMETER;
default:
- DEBUG(1, ("GSS(krb5) Update failed: %s\n",
+ DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n",
+ gensec_gssapi_state->gss_exchange_count,
gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
return nt_status;
}
} else {
- DEBUG(1, ("GSS Update failed: %s\n",
+ DEBUG(1, ("GSS Update(%d) failed: %s\n",
+ gensec_gssapi_state->gss_exchange_count,
gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
return nt_status;
}
@@ -583,7 +598,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
&conf_state,
&output_token);
if (GSS_ERROR(maj_stat)) {
- DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
+ DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
return NT_STATUS_ACCESS_DENIED;
}
@@ -648,7 +663,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
&conf_state,
&output_token);
if (GSS_ERROR(maj_stat)) {
- DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
+ DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
return NT_STATUS_ACCESS_DENIED;
}
@@ -1185,38 +1200,57 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
return NT_STATUS_NO_MEMORY;
}
- maj_stat = gss_krb5_copy_service_keyblock(&min_stat,
- gensec_gssapi_state->gssapi_context,
- &keyblock);
-
- if (maj_stat == 0) {
- maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
- gensec_gssapi_state->gssapi_context,
- &authtime);
- }
-
- if (maj_stat == 0) {
- maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
- gensec_gssapi_state->gssapi_context,
- KRB5_AUTHDATA_WIN2K_PAC,
- &pac);
- }
-
+ maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
+ gensec_gssapi_state->gssapi_context,
+ KRB5_AUTHDATA_WIN2K_PAC,
+ &pac);
+
+
if (maj_stat == 0) {
pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length);
gss_release_buffer(&min_stat, &pac);
+
+ } else {
+ pac_blob = data_blob(NULL, 0);
}
/* IF we have the PAC - otherwise we need to get this
* data from elsewere - local ldb, or (TODO) lookup of some
* kind...
*/
- if (maj_stat == 0) {
+ if (pac_blob.length) {
krb5_error_code ret;
+ union netr_Validation validation;
- ret = krb5_parse_name(gensec_gssapi_state->smb_krb5_context->krb5_context,
- principal_string, &principal);
+ 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)));
+ talloc_free(mem_ctx);
+ return NT_STATUS_FOOBAR;
+ }
+
+ maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
+ gensec_gssapi_state->gssapi_context,
+ &keyblock);
+
+ if (GSS_ERROR(maj_stat)) {
+ DEBUG(1, ("gsskrb5_copy_service_keyblock 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;
}
@@ -1226,25 +1260,25 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
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)) {
- union netr_Validation validation;
- 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)) {
- talloc_free(mem_ctx);
- return nt_status;
- }
- } else {
- maj_stat = 1;
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
}
- }
-
- if (maj_stat) {
- DEBUG(1, ("Unable to use PAC, resorting to local user lookup!\n"));
+ 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)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
+ } else if (!lp_parm_bool(-1, "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, principal_string,
&server_info);
@@ -1252,6 +1286,11 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
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;
}
/* references the server_info into the session_info */
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index d84f3dedf5..66d2801520 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -527,6 +527,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
struct PAC_LOGON_INFO *logon_info;
krb5_principal client_principal;
+ char *principal_string;
DATA_BLOB pac;
krb5_data pac_data;
@@ -538,30 +539,63 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
return NT_STATUS_NO_MEMORY;
}
+ ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
+ if (ret) {
+ DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
+ smb_get_krb5_error_message(context,
+ ret, mem_ctx)));
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context,
+ client_principal, &principal_string);
+ if (ret) {
+ DEBUG(1, ("Unable to parse client principal: %s\n",
+ smb_get_krb5_error_message(context,
+ ret, mem_ctx)));
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket,
KRB5_AUTHDATA_WIN2K_PAC,
&pac_data);
- if (ret) {
+ if (ret && lp_parm_bool(-1, "gensec", "require_pac", False)) {
+ DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s \n",
+ principal_string,
+ smb_get_krb5_error_message(context,
+ ret, mem_ctx)));
+ krb5_free_principal(context, client_principal);
+ free(principal_string);
+ return NT_STATUS_ACCESS_DENIED;
+ } else if (ret) {
+ /* NO pac */
DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n",
smb_get_krb5_error_message(context,
ret, mem_ctx)));
+ nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
+ &server_info);
+ krb5_free_principal(context, client_principal);
+ free(principal_string);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
} else {
+ /* Found pac */
+ union netr_Validation validation;
+ free(principal_string);
+
pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length);
if (!pac.data) {
+ krb5_free_principal(context, client_principal);
talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
- ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
- if (ret) {
- DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
- smb_get_krb5_error_message(context,
- ret, mem_ctx)));
- talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
/* decode and verify the pac */
nt_status = kerberos_pac_logon_info(gensec_krb5_state, &logon_info, pac,
gensec_krb5_state->smb_krb5_context->krb5_context,
@@ -570,46 +604,16 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
gensec_krb5_state->ticket->ticket.authtime, NULL);
krb5_free_principal(context, client_principal);
- if (NT_STATUS_IS_OK(nt_status)) {
- union netr_Validation validation;
- validation.sam3 = &logon_info->info3;
- nt_status = make_server_info_netlogon_validation(mem_ctx,
- NULL,
- 3, &validation,
- &server_info);
- }
- }
-
-
-
- /* IF we have the PAC - otherwise we need to get this
- * data from elsewere - local ldb, or (TODO) lookup of some
- * kind...
- */
- if (!NT_STATUS_IS_OK(nt_status)) {
- /* NO pac, or can't parse or verify it */
- char *principal_string;
- ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
- if (ret) {
- DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
- smb_get_krb5_error_message(context,
- ret, mem_ctx)));
- talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context,
- client_principal, &principal_string);
- krb5_free_principal(context, client_principal);
- if (ret) {
+ if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
+ return nt_status;
}
- nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
- &server_info);
- free(principal_string);
-
+ validation.sam3 = &logon_info->info3;
+ nt_status = make_server_info_netlogon_validation(mem_ctx,
+ NULL,
+ 3, &validation,
+ &server_info);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return nt_status;
diff --git a/source4/auth/kerberos/kerberos.c b/source4/auth/kerberos/kerberos.c
index 06f0c186a3..2b4c5d4cb0 100644
--- a/source4/auth/kerberos/kerberos.c
+++ b/source4/auth/kerberos/kerberos.c
@@ -45,6 +45,8 @@
krb5_get_init_creds_opt_init(&options);
+ krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options);
+
if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock,
0, NULL, &options))) {
return code;
@@ -87,6 +89,8 @@
krb5_get_init_creds_opt_init(&options);
+ krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options);
+
if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password,
NULL,
NULL, 0, NULL, &options))) {
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index dcfe16c896..8e1801f745 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -280,7 +280,8 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
return NT_STATUS_ACCESS_DENIED;
}
- ret = krb5_parse_name_norealm(context, logon_name->account_name, &client_principal_pac);
+ ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM,
+ &client_principal_pac);
if (ret) {
DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
logon_name->account_name,
@@ -591,7 +592,8 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
u_LOGON_INFO->logon_info.info = LOGON_INFO;
LOGON_INFO->info3 = *sam3;
- ret = krb5_unparse_name_norealm(context, client_principal, &name);
+ ret = krb5_unparse_name_flags(context, client_principal,
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
if (ret) {
return ret;
}
diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c
index d895d7a336..a3ef895b16 100644
--- a/source4/auth/kerberos/krb5_init_context.c
+++ b/source4/auth/kerberos/krb5_init_context.c
@@ -23,6 +23,7 @@
#include "includes.h"
#include "system/kerberos.h"
+#include "heimdal/lib/krb5/krb5_locl.h"
#include "auth/kerberos/kerberos.h"
#include "lib/socket/socket.h"
#include "system/network.h"
@@ -69,7 +70,7 @@ static void smb_krb5_debug_close(void *private) {
static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private)
{
- DEBUG(3, ("Kerberos: %s\n", msg));
+ DEBUG(2, ("Kerberos: %s\n", msg));
}
/*
@@ -224,11 +225,11 @@ static void smb_krb5_socket_handler(struct event_context *ev, struct fd_event *f
}
-static krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
- void *data,
- krb5_krbhst_info *hi,
- const krb5_data *send_buf,
- krb5_data *recv_buf)
+krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
+ void *data,
+ krb5_krbhst_info *hi,
+ const krb5_data *send_buf,
+ krb5_data *recv_buf)
{
krb5_error_code ret;
NTSTATUS status;
@@ -363,13 +364,6 @@ static krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
return KRB5_KDC_UNREACH;
}
-/* NO internal data, so nothing to free */
-static void smb_krb5_send_and_recv_close_func(krb5_context context, void *data)
-{
- return;
-}
-
-
krb5_error_code smb_krb5_init_context(void *parent_ctx,
struct smb_krb5_context **smb_krb5_context)
{
@@ -437,9 +431,9 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx,
ev = event_context_find(*smb_krb5_context);
/* Set use of our socket lib */
- ret = krb5_set_send_recv_func((*smb_krb5_context)->krb5_context,
- smb_krb5_send_and_recv_func,
- smb_krb5_send_and_recv_close_func, ev);
+ ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context,
+ smb_krb5_send_and_recv_func,
+ ev);
if (ret) {
DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx)));
@@ -454,12 +448,8 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx,
/* Set options in kerberos */
- (*smb_krb5_context)->krb5_context->fdns = FALSE;
+ krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context, FALSE);
return 0;
}
- void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context)
-{
- talloc_free(smb_krb5_context);
-}
diff --git a/source4/auth/kerberos/krb5_init_context.h b/source4/auth/kerberos/krb5_init_context.h
index f3ffc067fa..7aad97e2ca 100644
--- a/source4/auth/kerberos/krb5_init_context.h
+++ b/source4/auth/kerberos/krb5_init_context.h
@@ -27,3 +27,8 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx,
struct smb_krb5_context **smb_krb5_context);
void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context);
+krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
+ void *data,
+ krb5_krbhst_info *hi,
+ const krb5_data *send_buf,
+ krb5_data *recv_buf);