summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth')
-rw-r--r--source4/auth/gensec/gensec_gssapi.c19
-rw-r--r--source4/auth/gensec/gensec_krb5.c148
-rw-r--r--source4/auth/kerberos/kerberos.h9
-rw-r--r--source4/auth/kerberos/kerberos_util.c59
-rw-r--r--source4/auth/ntlmssp/ntlmssp_client.c55
5 files changed, 121 insertions, 169 deletions
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 64a6f8be77..26494f0222 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -208,6 +208,8 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
{
struct gensec_gssapi_state *gensec_gssapi_state;
struct cli_credentials *creds = gensec_get_credentials(gensec_security);
+ struct ccache_container *ccache;
+ krb5_error_code ret;
NTSTATUS nt_status;
gss_buffer_desc name_token;
OM_uint32 maj_stat, min_stat;
@@ -245,6 +247,13 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
return NT_STATUS_INVALID_PARAMETER;
}
+ ret = cli_credentials_get_ccache(creds,
+ &ccache);
+ if (ret) {
+ DEBUG(1, ("Failed to get CCACHE for gensec_gssapi: %s\n", error_message(ret)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
name_token.value = cli_credentials_get_principal(creds,
gensec_gssapi_state);
name_token.length = strlen(name_token.value);
@@ -260,16 +269,8 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
return NT_STATUS_UNSUCCESSFUL;
}
- nt_status = kinit_to_ccache(gensec_gssapi_state,
- creds,
- gensec_gssapi_state->smb_krb5_context,
- &gensec_gssapi_state->ccache, &gensec_gssapi_state->ccache_name);
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
-
maj_stat = gsskrb5_acquire_cred(&min_stat,
- NULL, gensec_gssapi_state->ccache,
+ NULL, ccache->ccache,
gensec_gssapi_state->client_name,
GSS_C_INDEFINITE,
GSS_C_NULL_OID_SET,
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index a89f46a411..09722af10b 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -45,7 +45,6 @@ struct gensec_krb5_state {
enum GENSEC_KRB5_STATE state_position;
struct smb_krb5_context *smb_krb5_context;
krb5_auth_context auth_context;
- krb5_ccache ccache;
krb5_data ticket;
krb5_keyblock *keyblock;
char *peer_principal;
@@ -75,7 +74,6 @@ static int gensec_krb5_destory(void *ptr)
static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
{
struct gensec_krb5_state *gensec_krb5_state;
- krb5_error_code ret = 0;
gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state);
if (!gensec_krb5_state) {
@@ -85,7 +83,6 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
gensec_security->private_data = gensec_krb5_state;
gensec_krb5_state->auth_context = NULL;
- gensec_krb5_state->ccache = NULL;
ZERO_STRUCT(gensec_krb5_state->ticket);
ZERO_STRUCT(gensec_krb5_state->keyblock);
gensec_krb5_state->session_key = data_blob(NULL, 0);
@@ -93,34 +90,29 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
talloc_set_destructor(gensec_krb5_state, gensec_krb5_destory);
- ret = smb_krb5_init_context(gensec_krb5_state,
- &gensec_krb5_state->smb_krb5_context);
- if (ret) {
- DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
- error_message(ret)));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context);
- if (ret) {
- DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n",
- smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
- ret, gensec_krb5_state)));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
return NT_STATUS_OK;
}
static NTSTATUS gensec_krb5_server_start(struct gensec_security *gensec_security)
{
NTSTATUS nt_status;
+ krb5_error_code ret = 0;
struct gensec_krb5_state *gensec_krb5_state;
nt_status = gensec_krb5_start(gensec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
+
+ gensec_krb5_state = gensec_security->private_data;
+
+ ret = smb_krb5_init_context(gensec_krb5_state,
+ &gensec_krb5_state->smb_krb5_context);
+ if (ret) {
+ DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
+ error_message(ret)));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
gensec_krb5_state = gensec_security->private_data;
gensec_krb5_state->state_position = GENSEC_KRB5_SERVER_START;
@@ -133,7 +125,7 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
struct gensec_krb5_state *gensec_krb5_state;
krb5_error_code ret;
NTSTATUS nt_status;
- const char *ccache_name;
+ struct ccache_container *ccache_container;
const char *hostname = gensec_get_target_hostname(gensec_security);
if (!hostname) {
@@ -154,72 +146,68 @@ static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security
gensec_krb5_state = gensec_security->private_data;
gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START;
- /* TODO: This is effecivly a static/global variable...
-
- TODO: If the user set a username, we should use an in-memory CCACHE (see below)
- */
- ret = krb5_cc_default(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->ccache);
+ ret = cli_credentials_get_ccache(gensec_security->credentials, &ccache_container);
if (ret) {
- DEBUG(1,("krb5_cc_default failed (%s)\n",
- smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
- return NT_STATUS_INTERNAL_ERROR;
+ DEBUG(1,("gensec_krb5_start: cli_credentials_get_ccache failed: %s\n",
+ error_message(ret)));
+ return NT_STATUS_UNSUCCESSFUL;
}
-
- while (1) {
- {
- 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, gensec_krb5_state->ccache,
- &gensec_krb5_state->ticket);
-
- }
- switch (ret) {
- case 0:
- return NT_STATUS_OK;
- case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
- DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
- hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
- return NT_STATUS_ACCESS_DENIED;
- case KRB5KDC_ERR_PREAUTH_FAILED:
- case KRB5KRB_AP_ERR_TKT_EXPIRED:
- case KRB5_CC_END:
- /* Too much clock skew - we will need to kinit to re-skew the clock */
- case KRB5KRB_AP_ERR_SKEW:
- case KRB5_KDCREP_SKEW:
- {
- DEBUG(3, ("kerberos (mk_req) failed: %s\n",
- smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
- /* fall down to remaining code */
- }
+ gensec_krb5_state->smb_krb5_context = talloc_reference(gensec_krb5_state, ccache_container->smb_krb5_context);
- /* just don't print a message for these really ordinary messages */
- case KRB5_FCC_NOFILE:
- case KRB5_CC_NOTFOUND:
- case ENOENT:
-
- nt_status = kinit_to_ccache(gensec_krb5_state,
- gensec_security->credentials,
- gensec_krb5_state->smb_krb5_context,
- &gensec_krb5_state->ccache,
- &ccache_name);
+ ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context);
+ if (ret) {
+ DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n",
+ smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
+ ret, gensec_krb5_state)));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ if (!ret) {
+ krb5_data in_data;
+ in_data.length = 0;
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
+ 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->ticket);
+
+ }
+ switch (ret) {
+ case 0:
+ return NT_STATUS_OK;
+ case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
+ DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
+ hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
+ return NT_STATUS_ACCESS_DENIED;
+ case KRB5KDC_ERR_PREAUTH_FAILED:
+ case KRB5KRB_AP_ERR_TKT_EXPIRED:
+ case KRB5_CC_END:
+ /* Too much clock skew - we will need to kinit to re-skew the clock */
+ case KRB5KRB_AP_ERR_SKEW:
+ case KRB5_KDCREP_SKEW:
+ {
+ DEBUG(3, ("kerberos (mk_req) failed: %s\n",
+ smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
+ /* fall down to remaining code */
+ }
+
+
+ /* just don't print a message for these really ordinary messages */
+ case KRB5_FCC_NOFILE:
+ case KRB5_CC_NOTFOUND:
+ case ENOENT:
+
+ return NT_STATUS_UNSUCCESSFUL;
break;
-
- default:
- DEBUG(0, ("kerberos: %s\n",
- smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
- return NT_STATUS_UNSUCCESSFUL;
- }
+
+ default:
+ DEBUG(0, ("kerberos: %s\n",
+ smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
+ return NT_STATUS_UNSUCCESSFUL;
}
}
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index 954ac7dc57..8cc8e561ac 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -34,6 +34,10 @@ struct smb_krb5_context {
#endif
};
+struct ccache_container {
+ struct smb_krb5_context *smb_krb5_context;
+ krb5_ccache ccache;
+};
/* not really ASN.1, but RFC 1964 */
#define TOK_ID_KRB_AP_REQ "\x01\x00"
@@ -111,11 +115,10 @@ BOOL kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, k
void kerberos_free_data_contents(krb5_context context, krb5_data *pdata);
krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry);
char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx);
-NTSTATUS kinit_to_ccache(TALLOC_CTX *parent_ctx,
+ krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
struct cli_credentials *credentials,
struct smb_krb5_context *smb_krb5_context,
- krb5_ccache *ccache,
- const char **ccache_name);
+ krb5_ccache ccache);
krb5_error_code smb_krb5_init_context(TALLOC_CTX *parent_ctx,
struct smb_krb5_context **smb_krb5_context);
krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index d455dac572..9dc8621b0e 100644
--- a/source4/auth/kerberos/kerberos_util.c
+++ b/source4/auth/kerberos/kerberos_util.c
@@ -33,11 +33,6 @@ struct principal_container {
krb5_principal principal;
};
-struct ccache_container {
- struct smb_krb5_context *smb_krb5_context;
- krb5_ccache ccache;
-};
-
struct keytab_container {
struct smb_krb5_context *smb_krb5_context;
krb5_keytab keytab;
@@ -65,7 +60,7 @@ krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
return ENOMEM;
}
- machine_username = talloc_strdup(mem_ctx, cli_credentials_get_username(machine_account));
+ machine_username = talloc_strdup(mem_ctx, cli_credentials_get_username(machine_account, mem_ctx));
if (!machine_username) {
talloc_free(mem_ctx);
@@ -100,58 +95,30 @@ krb5_error_code salt_principal_from_credentials(TALLOC_CTX *parent_ctx,
return ret;
}
-static int free_ccache(void *ptr) {
- struct ccache_container *ccc = ptr;
- /* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
- krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache);
-
- return 0;
-}
-
/**
* Return a freshly allocated ccache (destroyed by destructor on child
* of parent_ctx), for a given set of client credentials
*/
- NTSTATUS kinit_to_ccache(TALLOC_CTX *parent_ctx,
+ krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
struct cli_credentials *credentials,
struct smb_krb5_context *smb_krb5_context,
- krb5_ccache *ccache,
- const char **ccache_name)
+ krb5_ccache ccache)
{
krb5_error_code ret;
const char *password;
- char *ccache_string;
time_t kdc_time = 0;
- struct ccache_container *mem_ctx = talloc(parent_ctx, struct ccache_container);
+
+ TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
if (!mem_ctx) {
- return NT_STATUS_NO_MEMORY;
+ return ENOMEM;
}
password = cli_credentials_get_password(credentials);
- /* this string should be unique */
- ccache_string = talloc_asprintf(mem_ctx, "MEMORY:%s_%s",
- cli_credentials_get_principal(credentials, mem_ctx),
- generate_random_str(mem_ctx, 16));
-
- ret = krb5_cc_resolve(smb_krb5_context->krb5_context, ccache_string, ccache);
- if (ret) {
- DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n",
- ccache_string,
- error_message(ret)));
- talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
- mem_ctx->ccache = *ccache;
-
- talloc_set_destructor(mem_ctx, free_ccache);
-
if (password) {
- ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, *ccache,
+ ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache,
cli_credentials_get_principal(credentials, mem_ctx),
password, NULL, &kdc_time);
} else {
@@ -163,7 +130,7 @@ static int free_ccache(void *ptr) {
if (!mach_pwd) {
talloc_free(mem_ctx);
DEBUG(1, ("kinit_to_ccache: No password available for kinit\n"));
- return NT_STATUS_WRONG_PASSWORD;
+ return EINVAL;
}
ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
ENCTYPE_ARCFOUR_HMAC,
@@ -171,7 +138,7 @@ static int free_ccache(void *ptr) {
&keyblock);
if (ret == 0) {
- ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, *ccache,
+ ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, ccache,
cli_credentials_get_principal(credentials, mem_ctx),
&keyblock, NULL, &kdc_time);
krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
@@ -192,7 +159,7 @@ static int free_ccache(void *ptr) {
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
ret, mem_ctx)));
talloc_free(mem_ctx);
- return NT_STATUS_TIME_DIFFERENCE_AT_DC;
+ return ret;
}
if (ret) {
DEBUG(1,("kinit for %s failed (%s)\n",
@@ -200,11 +167,9 @@ static int free_ccache(void *ptr) {
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
ret, mem_ctx)));
talloc_free(mem_ctx);
- return NT_STATUS_WRONG_PASSWORD;
+ return ret;
}
- *ccache_name = ccache_string;
-
- return NT_STATUS_OK;
+ return 0;
}
static int free_keytab(void *ptr) {
diff --git a/source4/auth/ntlmssp/ntlmssp_client.c b/source4/auth/ntlmssp/ntlmssp_client.c
index add774f84e..feee14a857 100644
--- a/source4/auth/ntlmssp/ntlmssp_client.c
+++ b/source4/auth/ntlmssp/ntlmssp_client.c
@@ -164,20 +164,10 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
return NT_STATUS_INVALID_PARAMETER;
}
- /* Correctly handle username in the original form of user@REALM, which is valid */
- if (gensec_security->credentials->realm_obtained
- > gensec_security->credentials->domain_obtained) {
- user = talloc_asprintf(out_mem_ctx, "%s@%s",
- cli_credentials_get_username(gensec_security->credentials),
- cli_credentials_get_realm(gensec_security->credentials));
- domain = NULL;
- } else {
- user = cli_credentials_get_username(gensec_security->credentials);
- domain = cli_credentials_get_domain(gensec_security->credentials);
- }
+ user = cli_credentials_get_username(gensec_security->credentials, out_mem_ctx);
+ domain = cli_credentials_get_domain(gensec_security->credentials);
nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials, out_mem_ctx);
- password = cli_credentials_get_password(gensec_security->credentials);
if (!nt_hash) {
static const uint8_t zeros[16];
@@ -265,24 +255,29 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
}
/* lanman auth is insecure, it may be disabled. We may also not have a password */
- if (lp_client_lanman_auth() && password) {
- lm_response = data_blob_talloc(gensec_ntlmssp_state, NULL, 24);
- if (!SMBencrypt(password,challenge_blob.data,
- lm_response.data)) {
- /* If the LM password was too long (and therefore the LM hash being
- of the first 14 chars only), don't send it */
- data_blob_free(&lm_response);
-
- /* LM Key is incompatible with 'long' passwords */
- gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
+ if (lp_client_lanman_auth()) {
+ password = cli_credentials_get_password(gensec_security->credentials);
+ if (!password) {
+ lm_response = nt_response;
} else {
- E_deshash(password, lm_hash);
- lm_session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
- memcpy(lm_session_key.data, lm_hash, 8);
- memset(&lm_session_key.data[8], '\0', 8);
-
- if (!gensec_ntlmssp_state->use_nt_response) {
+ lm_response = data_blob_talloc(gensec_ntlmssp_state, NULL, 24);
+ if (!SMBencrypt(password,challenge_blob.data,
+ lm_response.data)) {
+ /* If the LM password was too long (and therefore the LM hash being
+ of the first 14 chars only), don't send it */
+ data_blob_free(&lm_response);
+
+ /* LM Key is incompatible with 'long' passwords */
+ gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
+ } else {
+ E_deshash(password, lm_hash);
+ lm_session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
+ memcpy(lm_session_key.data, lm_hash, 8);
+ memset(&lm_session_key.data[8], '\0', 8);
+
+ if (!gensec_ntlmssp_state->use_nt_response) {
session_key = lm_session_key;
+ }
}
}
} else {
@@ -353,7 +348,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
gensec_ntlmssp_state->expected_state = NTLMSSP_DONE;
- if (gensec_security->want_features & GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL) {
+ if (gensec_security->want_features & (GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL)) {
nt_status = ntlmssp_sign_init(gensec_ntlmssp_state);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
@@ -362,7 +357,7 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
}
}
- return nt_status;
+ return NT_STATUS_OK;
}
NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)