summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/gensec/gensec.c32
-rw-r--r--source4/auth/gensec/gensec_gssapi.c20
-rw-r--r--source4/auth/gensec/gensec_krb5.c48
-rw-r--r--source4/auth/gensec/spnego.c3
-rw-r--r--source4/param/loadparm.c4
5 files changed, 85 insertions, 22 deletions
diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c
index f0256b9668..21e70e1c0e 100644
--- a/source4/auth/gensec/gensec.c
+++ b/source4/auth/gensec/gensec.c
@@ -707,6 +707,15 @@ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, cons
return NT_STATUS_OK;
}
+const char *gensec_get_target_service(struct gensec_security *gensec_security)
+{
+ if (gensec_security->target.service) {
+ return gensec_security->target.service;
+ }
+
+ return "host";
+}
+
/**
* Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
*
@@ -731,13 +740,28 @@ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
return NULL;
}
-const char *gensec_get_target_service(struct gensec_security *gensec_security)
+/**
+ * Set the target principal (assuming it it known, say from the SPNEGO reply)
+ * - ensures it is talloc()ed
+ *
+ */
+
+NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
{
- if (gensec_security->target.service) {
- return gensec_security->target.service;
+ gensec_security->target.principal = talloc_strdup(gensec_security, principal);
+ if (!gensec_security->target.principal) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
+
+const char *gensec_get_target_principal(struct gensec_security *gensec_security)
+{
+ if (gensec_security->target.principal) {
+ return gensec_security->target.principal;
}
- return "host";
+ return NULL;
}
/*
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 69f219fe07..c462cf0ecd 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -229,8 +229,10 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
krb5_error_code ret;
NTSTATUS nt_status;
gss_buffer_desc name_token;
+ gss_OID name_type;
OM_uint32 maj_stat, min_stat;
const char *hostname = gensec_get_target_hostname(gensec_security);
+ const char *principal;
if (!hostname) {
DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
@@ -248,14 +250,22 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
gensec_gssapi_state = gensec_security->private_data;
- name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s",
- gensec_get_target_service(gensec_security),
- hostname);
- name_token.length = strlen(name_token.value);
+ principal = gensec_get_target_principal(gensec_security);
+ if (principal && lp_client_use_spnego_principal()) {
+ name_token.value = gensec_get_target_principal(gensec_security);
+ name_token.length = strlen(name_token.value);
+ name_type = GSS_C_NULL_OID;
+ } else {
+ name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s",
+ gensec_get_target_service(gensec_security),
+ hostname);
+ name_token.length = strlen(name_token.value);
+ name_type = GSS_C_NT_HOSTBASED_SERVICE;
+ }
maj_stat = gss_import_name (&min_stat,
&name_token,
- GSS_C_NT_HOSTBASED_SERVICE,
+ name_type,
&gensec_gssapi_state->server_name);
if (maj_stat) {
DEBUG(2, ("GSS Import name of %s failed: %s\n",
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index d4147496fd..3fa2ccd6de 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -50,10 +50,14 @@ struct gensec_krb5_state {
krb5_ticket *ticket;
};
-static int gensec_krb5_destory(void *ptr)
+static int gensec_krb5_destroy(void *ptr)
{
struct gensec_krb5_state *gensec_krb5_state = ptr;
+ if (!gensec_krb5_state->smb_krb5_context) {
+ /* We can't clean anything else up unless we started up this far */
+ return 0;
+ }
if (gensec_krb5_state->enc_ticket.length) {
kerberos_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
&gensec_krb5_state->enc_ticket);
@@ -88,6 +92,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
gensec_security->private_data = gensec_krb5_state;
+ gensec_krb5_state->smb_krb5_context = NULL;
gensec_krb5_state->auth_context = NULL;
gensec_krb5_state->ticket = NULL;
ZERO_STRUCT(gensec_krb5_state->enc_ticket);
@@ -95,7 +100,7 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
gensec_krb5_state->session_key = data_blob(NULL, 0);
gensec_krb5_state->pac = data_blob(NULL, 0);
- talloc_set_destructor(gensec_krb5_state, gensec_krb5_destory);
+ talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy);
return NT_STATUS_OK;
}
@@ -141,8 +146,10 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
krb5_error_code ret;
NTSTATUS nt_status;
struct ccache_container *ccache_container;
+ const char *hostname;
+ krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED;
- const char *hostname = gensec_get_target_hostname(gensec_security);
+ hostname = gensec_get_target_hostname(gensec_security);
if (!hostname) {
DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
return NT_STATUS_INVALID_PARAMETER;
@@ -178,18 +185,35 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
return NT_STATUS_INTERNAL_ERROR;
}
- if (!ret) {
+ if (ret == 0) {
+ char *principal;
krb5_data in_data;
in_data.length = 0;
- ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context,
- &gensec_krb5_state->auth_context,
- AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED,
- gensec_get_target_service(gensec_security),
- hostname,
- &in_data, ccache_container->ccache,
- &gensec_krb5_state->enc_ticket);
-
+ principal = gensec_get_target_principal(gensec_security);
+ if (principal && lp_client_use_spnego_principal()) {
+ krb5_principal target_principal;
+ ret = krb5_parse_name(gensec_krb5_state->smb_krb5_context->krb5_context, principal,
+ &target_principal);
+ if (ret == 0) {
+ ret = krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context,
+ &gensec_krb5_state->auth_context,
+ ap_req_options,
+ target_principal,
+ &in_data, ccache_container->ccache,
+ &gensec_krb5_state->enc_ticket);
+ krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context,
+ target_principal);
+ }
+ } else {
+ ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context,
+ &gensec_krb5_state->auth_context,
+ ap_req_options,
+ gensec_get_target_service(gensec_security),
+ hostname,
+ &in_data, ccache_container->ccache,
+ &gensec_krb5_state->enc_ticket);
+ }
}
switch (ret) {
case 0:
diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c
index 133530833b..570ca89f03 100644
--- a/source4/auth/gensec/spnego.c
+++ b/source4/auth/gensec/spnego.c
@@ -636,7 +636,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA
}
if (spnego.negTokenInit.targetPrincipal) {
- DEBUG(5, ("Server claims it's principal name is %s (ignored)\n", spnego.negTokenInit.targetPrincipal));
+ DEBUG(5, ("Server claims it's principal name is %s\n", spnego.negTokenInit.targetPrincipal));
+ gensec_set_target_principal(gensec_security, spnego.negTokenInit.targetPrincipal);
}
nt_status = gensec_spnego_parse_negTokenInit(gensec_security,
diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
index 3f6a22d404..244ce27419 100644
--- a/source4/param/loadparm.c
+++ b/source4/param/loadparm.c
@@ -184,6 +184,7 @@ typedef struct
BOOL bClientPlaintextAuth;
BOOL bClientLanManAuth;
BOOL bClientNTLMv2Auth;
+ BOOL client_use_spnego_principal;
BOOL bHostMSDfs;
BOOL bUnicode;
BOOL bUnixExtensions;
@@ -422,6 +423,7 @@ static struct parm_struct parm_table[] = {
{"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+ {"client use spnego principal", P_BOOL, P_GLOBAL, &Globals.client_use_spnego_principal, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
@@ -659,6 +661,7 @@ static void init_globals(void)
do_parameter("ClientLanManAuth", "True", NULL);
do_parameter("LanmanAuth", "True", NULL);
do_parameter("NTLMAuth", "True", NULL);
+ do_parameter("client use spnego principal", "False", NULL);
do_parameter("UnixExtensions", "False", NULL);
@@ -853,6 +856,7 @@ FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
+FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal)
FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)