summaryrefslogtreecommitdiff
path: root/source4/auth/credentials
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth/credentials')
-rw-r--r--source4/auth/credentials/credentials.c20
-rw-r--r--source4/auth/credentials/credentials_krb5.c75
-rw-r--r--source4/auth/credentials/credentials_krb5.h6
3 files changed, 81 insertions, 20 deletions
diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c
index 5f2658d5bd..6f7630a206 100644
--- a/source4/auth/credentials/credentials.c
+++ b/source4/auth/credentials/credentials.c
@@ -222,7 +222,7 @@ _PUBLIC_ const char *cli_credentials_get_bind_dn(struct cli_credentials *cred)
* @retval The username set on this context.
* @note Return value will never be NULL except by programmer error.
*/
-_PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
+const char *cli_credentials_get_principal_and_obtained(struct cli_credentials *cred, TALLOC_CTX *mem_ctx, enum credentials_obtained *obtained)
{
if (cred->machine_account_pending) {
cli_credentials_set_machine_account(cred,
@@ -238,20 +238,36 @@ _PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred,
cli_credentials_invalidate_ccache(cred, cred->principal_obtained);
}
- if (cred->principal_obtained < cred->username_obtained) {
+ if (cred->principal_obtained < cred->username_obtained
+ || cred->principal_obtained < MAX(cred->domain_obtained, cred->realm_obtained)) {
if (cred->domain_obtained > cred->realm_obtained) {
+ *obtained = MIN(cred->domain_obtained, cred->username_obtained);
return talloc_asprintf(mem_ctx, "%s@%s",
cli_credentials_get_username(cred),
cli_credentials_get_domain(cred));
} else {
+ *obtained = MIN(cred->domain_obtained, cred->username_obtained);
return talloc_asprintf(mem_ctx, "%s@%s",
cli_credentials_get_username(cred),
cli_credentials_get_realm(cred));
}
}
+ *obtained = cred->principal_obtained;
return talloc_reference(mem_ctx, cred->principal);
}
+/**
+ * Obtain the client principal for this credentials context.
+ * @param cred credentials context
+ * @retval The username set on this context.
+ * @note Return value will never be NULL except by programmer error.
+ */
+_PUBLIC_ const char *cli_credentials_get_principal(struct cli_credentials *cred, TALLOC_CTX *mem_ctx)
+{
+ enum credentials_obtained obtained;
+ return cli_credentials_get_principal_and_obtained(cred, mem_ctx, &obtained);
+}
+
bool cli_credentials_set_principal(struct cli_credentials *cred,
const char *val,
enum credentials_obtained obtained)
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
index d76073093b..12bf610bf8 100644
--- a/source4/auth/credentials/credentials_krb5.c
+++ b/source4/auth/credentials/credentials_krb5.c
@@ -27,6 +27,7 @@
#include "auth/credentials/credentials.h"
#include "auth/credentials/credentials_proto.h"
#include "auth/credentials/credentials_krb5.h"
+#include "auth/kerberos/kerberos_credentials.h"
#include "param/param.h"
_PUBLIC_ int cli_credentials_get_krb5_context(struct cli_credentials *cred,
@@ -282,6 +283,7 @@ _PUBLIC_ int cli_credentials_get_named_ccache(struct cli_credentials *cred,
const char **error_string)
{
krb5_error_code ret;
+ enum credentials_obtained obtained;
if (cred->machine_account_pending) {
cli_credentials_set_machine_account(cred, lp_ctx);
@@ -302,15 +304,13 @@ _PUBLIC_ int cli_credentials_get_named_ccache(struct cli_credentials *cred,
return ret;
}
- ret = kinit_to_ccache(cred, cred, (*ccc)->smb_krb5_context, (*ccc)->ccache, error_string);
+ ret = kinit_to_ccache(cred, cred, (*ccc)->smb_krb5_context, (*ccc)->ccache, &obtained, error_string);
if (ret) {
return ret;
}
ret = cli_credentials_set_from_ccache(cred, *ccc,
- (MAX(MAX(cred->principal_obtained,
- cred->username_obtained),
- cred->password_obtained)), error_string);
+ obtained, error_string);
cred->ccache = *ccc;
cred->ccache_obtained = cred->principal_obtained;
@@ -330,6 +330,16 @@ _PUBLIC_ int cli_credentials_get_ccache(struct cli_credentials *cred,
return cli_credentials_get_named_ccache(cred, event_ctx, lp_ctx, NULL, ccc, error_string);
}
+/* We have good reason to think the ccache in these credentials is invalid - blow it away */
+static void cli_credentials_unconditionally_invalidate_client_gss_creds(struct cli_credentials *cred)
+{
+ if (cred->client_gss_creds_obtained > CRED_UNINITIALISED) {
+ talloc_unlink(cred, cred->client_gss_creds);
+ cred->client_gss_creds = NULL;
+ }
+ cred->client_gss_creds_obtained = CRED_UNINITIALISED;
+}
+
void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred,
enum credentials_obtained obtained)
{
@@ -351,6 +361,18 @@ void cli_credentials_invalidate_client_gss_creds(struct cli_credentials *cred,
}
}
+/* We have good reason to think this CCACHE is invalid. Blow it away */
+static void cli_credentials_unconditionally_invalidate_ccache(struct cli_credentials *cred)
+{
+ if (cred->ccache_obtained > CRED_UNINITIALISED) {
+ talloc_unlink(cred, cred->ccache);
+ cred->ccache = NULL;
+ }
+ cred->ccache_obtained = CRED_UNINITIALISED;
+
+ cli_credentials_unconditionally_invalidate_client_gss_creds(cred);
+}
+
_PUBLIC_ void cli_credentials_invalidate_ccache(struct cli_credentials *cred,
enum credentials_obtained obtained)
{
@@ -416,6 +438,23 @@ _PUBLIC_ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL,
&gcc->creds);
+ if ((maj_stat == GSS_S_FAILURE) && (min_stat == (OM_uint32)KRB5_CC_END || min_stat == (OM_uint32) KRB5_CC_NOTFOUND)) {
+ /* This CCACHE is no good. Ensure we don't use it again */
+ cli_credentials_unconditionally_invalidate_ccache(cred);
+
+ /* Now try again to get a ccache */
+ ret = cli_credentials_get_ccache(cred, event_ctx, lp_ctx,
+ &ccache, error_string);
+ if (ret) {
+ DEBUG(1, ("Failed to re-get CCACHE for GSSAPI client: %s\n", error_message(ret)));
+ return ret;
+ }
+
+ maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL,
+ &gcc->creds);
+
+ }
+
if (maj_stat) {
talloc_free(gcc);
if (min_stat) {
@@ -698,12 +737,11 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
TALLOC_CTX *mem_ctx;
krb5_principal princ;
const char *error_string;
+ enum credentials_obtained obtained;
- if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained,
- MAX(cred->principal_obtained,
- cred->username_obtained)))) {
- *_gcc = cred->server_gss_creds;
- return 0;
+ mem_ctx = talloc_new(cred);
+ if (!mem_ctx) {
+ return ENOMEM;
}
ret = cli_credentials_get_krb5_context(cred, event_ctx, lp_ctx, &smb_krb5_context);
@@ -711,22 +749,23 @@ _PUBLIC_ int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
return ret;
}
- ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
+ ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ, &obtained, &error_string);
if (ret) {
- DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
+ DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
+ error_string));
+ talloc_free(mem_ctx);
return ret;
}
- mem_ctx = talloc_new(cred);
- if (!mem_ctx) {
- return ENOMEM;
+ if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained, obtained))) {
+ talloc_free(mem_ctx);
+ *_gcc = cred->server_gss_creds;
+ return 0;
}
- ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ, &error_string);
+ ret = cli_credentials_get_keytab(cred, event_ctx, lp_ctx, &ktc);
if (ret) {
- DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
- error_string));
- talloc_free(mem_ctx);
+ DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
return ret;
}
diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h
index 72a4373609..3a614ff30e 100644
--- a/source4/auth/credentials/credentials_krb5.h
+++ b/source4/auth/credentials/credentials_krb5.h
@@ -44,6 +44,12 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
struct cli_credentials *credentials,
struct smb_krb5_context *smb_krb5_context,
krb5_principal *princ,
+ enum credentials_obtained *obtained,
const char **error_string);
+krb5_error_code impersonate_principal_from_credentials(TALLOC_CTX *parent_ctx,
+ struct cli_credentials *credentials,
+ struct smb_krb5_context *smb_krb5_context,
+ krb5_principal *princ,
+ const char **error_string);
#endif /* __CREDENTIALS_KRB5_H__ */