summaryrefslogtreecommitdiff
path: root/source4/auth/kerberos/kerberos_util.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-10-20 03:47:55 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:45:00 -0500
commit372ca26b2052e267711a45c8bf341f55505f3f8f (patch)
tree8c13e34fdac62ca762972d25cfe95b053bff93fa /source4/auth/kerberos/kerberos_util.c
parent9e25f33a1a06e1374bb643cb087af0e0bedb99c7 (diff)
downloadsamba-372ca26b2052e267711a45c8bf341f55505f3f8f.tar.gz
samba-372ca26b2052e267711a45c8bf341f55505f3f8f.tar.bz2
samba-372ca26b2052e267711a45c8bf341f55505f3f8f.zip
r11200: Reposition the creation of the kerberos keytab for GSSAPI and Krb5
authentication. This pulls the creating of the keytab back to the credentials code, and removes the special case of 'use keberos keytab = yes' for now. This allows (and requires) the callers to specify the credentials for the server credentails to GENSEC. This allows kpasswdd (soon to be added) to use a different set of kerberos credentials. The 'use kerberos keytab' code will be moved into the credentials layer, as the layers below now expect a keytab. We also now allow for the old secret to be stored into the credentials, allowing service password changes. Andrew Bartlett (This used to be commit 205f77c579ac8680c85f713a76de5767189c627b)
Diffstat (limited to 'source4/auth/kerberos/kerberos_util.c')
-rw-r--r--source4/auth/kerberos/kerberos_util.c111
1 files changed, 74 insertions, 37 deletions
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index 3a6aff9df8..3d7084aa0d 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 keytab_container {
- struct smb_krb5_context *smb_krb5_context;
- krb5_keytab keytab;
-};
-
static int free_principal(void *ptr) {
struct principal_container *pc = ptr;
/* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
@@ -111,7 +106,8 @@ krb5_error_code principal_from_credentials(TALLOC_CTX *parent_ctx,
if (!princ_string) {
talloc_free(mem_ctx);
- return EINVAL;
+ princ = NULL;
+ return 0;
}
ret = krb5_parse_name(smb_krb5_context->krb5_context,
@@ -131,9 +127,9 @@ krb5_error_code principal_from_credentials(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)
+ struct cli_credentials *credentials,
+ struct smb_krb5_context *smb_krb5_context,
+ krb5_ccache ccache)
{
krb5_error_code ret;
const char *password;
@@ -216,36 +212,40 @@ static int free_keytab(void *ptr) {
return 0;
}
- NTSTATUS create_memory_keytab(TALLOC_CTX *parent_ctx,
- struct cli_credentials *machine_account,
- struct smb_krb5_context *smb_krb5_context,
- krb5_keytab *keytab)
+ int create_memory_keytab(TALLOC_CTX *parent_ctx,
+ struct cli_credentials *machine_account,
+ struct smb_krb5_context *smb_krb5_context,
+ struct keytab_container **keytab_container)
{
krb5_error_code ret;
const char *password_s;
+ char *old_secret;
krb5_data password;
- int i;
- struct keytab_container *mem_ctx = talloc(parent_ctx, struct keytab_container);
+ int i, kvno;
krb5_enctype *enctypes;
krb5_principal salt_princ;
krb5_principal princ;
-
+ krb5_keytab keytab;
+
+ TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
if (!mem_ctx) {
- return NT_STATUS_NO_MEMORY;
+ return ENOMEM;
}
+
+ *keytab_container = talloc(mem_ctx, struct keytab_container);
- ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY:", keytab);
+ ret = krb5_kt_resolve(smb_krb5_context->krb5_context, "MEMORY:", &keytab);
if (ret) {
DEBUG(1,("failed to generate a new krb5 keytab: %s\n",
error_message(ret)));
talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
- mem_ctx->smb_krb5_context = talloc_reference(mem_ctx, smb_krb5_context);
- mem_ctx->keytab = *keytab;
+ (*keytab_container)->smb_krb5_context = talloc_reference(*keytab_container, smb_krb5_context);
+ (*keytab_container)->keytab = keytab;
- talloc_set_destructor(mem_ctx, free_keytab);
+ talloc_set_destructor(*keytab_container, free_keytab);
ret = salt_principal_from_credentials(mem_ctx, machine_account,
smb_krb5_context,
@@ -255,7 +255,7 @@ static int free_keytab(void *ptr) {
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
ret, mem_ctx)));
talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
@@ -264,10 +264,10 @@ static int free_keytab(void *ptr) {
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
ret, mem_ctx)));
talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
- password_s = talloc_strdup(mem_ctx, cli_credentials_get_password(machine_account));
+ password_s = cli_credentials_get_password(machine_account);
if (!password_s) {
/* If we don't have the plaintext password, try for
* the MD4 password hash */
@@ -279,7 +279,7 @@ static int free_keytab(void *ptr) {
talloc_free(mem_ctx);
DEBUG(1, ("create_memory_keytab: Domain trust informaton for account %s not available\n",
cli_credentials_get_principal(machine_account, mem_ctx)));
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ return EINVAL;
}
ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
ENCTYPE_ARCFOUR_HMAC,
@@ -289,12 +289,12 @@ static int free_keytab(void *ptr) {
DEBUG(1, ("create_memory_keytab: krb5_keyblock_init failed: %s\n",
smb_get_krb5_error_message(smb_krb5_context->krb5_context,
ret, mem_ctx)));
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
entry.principal = princ;
entry.vno = cli_credentials_get_kvno(machine_account);
- ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
+ ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
if (ret) {
DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s",
cli_credentials_get_principal(machine_account, mem_ctx),
@@ -302,11 +302,14 @@ static int free_keytab(void *ptr) {
ret, mem_ctx)));
talloc_free(mem_ctx);
krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
- return NT_STATUS_OK;
+
+ talloc_steal(parent_ctx, *keytab_container);
+ talloc_free(mem_ctx);
+ return 0;
}
/* good, we actually have the real plaintext */
@@ -317,24 +320,25 @@ static int free_keytab(void *ptr) {
DEBUG(1,("create_memory_keytab: getting encrption types failed (%s)\n",
error_message(ret)));
talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
password.data = discard_const_p(char *, password_s);
password.length = strlen(password_s);
-
+ kvno = cli_credentials_get_kvno(machine_account);
+
for (i=0; enctypes[i]; i++) {
krb5_keytab_entry entry;
ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context,
salt_princ, &password, &entry.keyblock, enctypes[i]);
if (ret) {
talloc_free(mem_ctx);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
entry.principal = princ;
- entry.vno = cli_credentials_get_kvno(machine_account);
- ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, *keytab, &entry);
+ entry.vno = kvno;
+ ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
if (ret) {
DEBUG(1, ("Failed to add entry for %s to keytab: %s",
cli_credentials_get_principal(machine_account, mem_ctx),
@@ -342,15 +346,48 @@ static int free_keytab(void *ptr) {
ret, mem_ctx)));
talloc_free(mem_ctx);
krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
- return NT_STATUS_INTERNAL_ERROR;
+ return ret;
}
krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
}
+ old_secret = cli_credentials_get_old_password(machine_account);
+ if (kvno != 0 && old_secret) {
+ password.data = discard_const_p(char *, old_secret);
+ password.length = strlen(old_secret);
+
+ for (i=0; enctypes[i]; i++) {
+ krb5_keytab_entry entry;
+ ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context,
+ salt_princ, &password, &entry.keyblock, enctypes[i]);
+ if (ret) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ entry.principal = princ;
+ entry.vno = kvno - 1;
+ ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
+ if (ret) {
+ DEBUG(1, ("Failed to add 'old password' entry for %s to keytab: %s",
+ cli_credentials_get_principal(machine_account, mem_ctx),
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+ talloc_free(mem_ctx);
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
+ return ret;
+ }
+
+ krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
+ }
+ }
+
free_kerberos_etypes(smb_krb5_context->krb5_context, enctypes);
- return NT_STATUS_OK;
+ talloc_steal(parent_ctx, *keytab_container);
+ talloc_free(mem_ctx);
+ return 0;
}