summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-12-01 05:20:39 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:46:56 -0500
commit9c6b7f2d62e134a4bc15efc04e05be25e4a53dc7 (patch)
tree8ef389a528fdc2caca79f279c086b4f8bea7afeb
parent22f1de0998ee34be4c032b16e4a6d30c9f8e6b85 (diff)
downloadsamba-9c6b7f2d62e134a4bc15efc04e05be25e4a53dc7.tar.gz
samba-9c6b7f2d62e134a4bc15efc04e05be25e4a53dc7.tar.bz2
samba-9c6b7f2d62e134a4bc15efc04e05be25e4a53dc7.zip
r11995: A big kerberos-related update.
This merges Samba4 up to current lorikeet-heimdal, which includes a replacement for some Samba-specific hacks. In particular, the credentials system now supplies GSS client and server credentials. These are imported into GSS with gss_krb5_import_creds(). Unfortunetly this can't take an MEMORY keytab, so we now create a FILE based keytab as provision and join time. Because the keytab is now created in advance, we don't spend .4s at negprot doing sha1 s2k calls. Also, because the keytab is read in real time, any change in the server key will be correctly picked up by the the krb5 code. To mark entries in the secrets which should be exported to a keytab, there is a new kerberosSecret objectClass. The new routine cli_credentials_update_all_keytabs() searches for these, and updates the keytabs. This is called in the provision.js via the ejs wrapper credentials_update_all_keytabs(). We can now (in theory) use a system-provided /etc/krb5.keytab, if krb5Keytab: FILE:/etc/krb5.keytab is added to the secrets.ldb record. By default the attribute privateKeytab: secrets.keytab is set, pointing to allow the whole private directory to be moved without breaking the internal links. (This used to be commit 6b75573df49c6210e1b9d71e108a9490976bd41d)
-rw-r--r--source4/auth/credentials/credentials.c27
-rw-r--r--source4/auth/credentials/credentials.h6
-rw-r--r--source4/auth/credentials/credentials_files.c92
-rw-r--r--source4/auth/credentials/credentials_krb5.c211
-rw-r--r--source4/auth/gensec/gensec_gssapi.c61
-rw-r--r--source4/heimdal/kdc/kerberos5.c25
-rw-r--r--source4/heimdal/lib/gssapi/accept_sec_context.c106
-rw-r--r--source4/heimdal/lib/gssapi/acquire_cred.c50
-rw-r--r--source4/heimdal/lib/gssapi/arcfour.c8
-rw-r--r--source4/heimdal/lib/gssapi/copy_ccache.c123
-rw-r--r--source4/heimdal/lib/gssapi/gssapi.h21
-rw-r--r--source4/heimdal/lib/gssapi/gssapi_locl.h2
-rw-r--r--source4/heimdal/lib/gssapi/init_sec_context.c2
-rw-r--r--source4/heimdal/lib/gssapi/release_cred.c2
-rw-r--r--source4/heimdal/lib/hdb/db.c6
-rw-r--r--source4/heimdal/lib/hdb/hdb-protos.h4
-rw-r--r--source4/heimdal/lib/hdb/ndbm.c2
-rw-r--r--source4/heimdal/lib/krb5/cache.c37
-rw-r--r--source4/heimdal/lib/krb5/get_for_creds.c22
-rw-r--r--source4/heimdal/lib/krb5/keytab.c36
-rw-r--r--source4/heimdal/lib/krb5/krb5-private.h17
-rw-r--r--source4/heimdal/lib/krb5/krb5-protos.h12
-rw-r--r--source4/heimdal/lib/krb5/rd_cred.c2
-rw-r--r--source4/libnet/libnet_join.c35
-rw-r--r--source4/scripting/ejs/smbcalls_creds.c12
-rw-r--r--source4/scripting/libjs/provision.js3
-rw-r--r--source4/setup/secrets.ldif4
27 files changed, 633 insertions, 295 deletions
diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c
index 86a3df0077..75c6795e73 100644
--- a/source4/auth/credentials/credentials.c
+++ b/source4/auth/credentials/credentials.c
@@ -46,7 +46,8 @@ struct cli_credentials *cli_credentials_init(TALLOC_CTX *mem_ctx)
cred->domain_obtained = CRED_UNINITIALISED;
cred->realm_obtained = CRED_UNINITIALISED;
cred->ccache_obtained = CRED_UNINITIALISED;
- cred->gss_creds_obtained = CRED_UNINITIALISED;
+ cred->client_gss_creds_obtained = CRED_UNINITIALISED;
+ cred->server_gss_creds_obtained = CRED_UNINITIALISED;
cred->keytab_obtained = CRED_UNINITIALISED;
cred->principal_obtained = CRED_UNINITIALISED;
@@ -148,6 +149,9 @@ BOOL cli_credentials_set_principal(struct cli_credentials *cred,
return False;
}
+/* Set a callback to get the principal. This could be a popup dialog,
+ * a terminal prompt or similar. */
+
BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred,
const char *(*principal_cb) (struct cli_credentials *))
{
@@ -160,6 +164,10 @@ BOOL cli_credentials_set_principal_callback(struct cli_credentials *cred,
return False;
}
+/* Some of our tools are 'anonymous by default'. This is a single
+ * function to determine if authentication has been explicitly
+ * requested */
+
BOOL cli_credentials_authentication_requested(struct cli_credentials *cred)
{
if (cred->principal_obtained >= CRED_SPECIFIED) {
@@ -190,6 +198,9 @@ const char *cli_credentials_get_password(struct cli_credentials *cred)
return cred->password;
}
+/* Set a password on the credentials context, including an indication
+ * of 'how' the password was obtained */
+
BOOL cli_credentials_set_password(struct cli_credentials *cred,
const char *val,
enum credentials_obtained obtained)
@@ -240,7 +251,11 @@ BOOL cli_credentials_set_old_password(struct cli_credentials *cred,
}
/**
- * Obtain the password for this credentials context.
+ * Obtain the password, in the form MD4(unicode(password)) for this credentials context.
+ *
+ * Sometimes we only have this much of the password, while the rest of
+ * the time this call avoids calling E_md4hash themselves.
+ *
* @param cred credentials context
* @retval If set, the cleartext password, otherwise NULL
*/
@@ -566,7 +581,13 @@ void cli_credentials_set_anonymous(struct cli_credentials *cred)
BOOL cli_credentials_is_anonymous(struct cli_credentials *cred)
{
- const char *username = cli_credentials_get_username(cred);
+ const char *username;
+
+ if (cred->machine_account_pending) {
+ cli_credentials_set_machine_account(cred);
+ }
+
+ username = cli_credentials_get_username(cred);
/* Yes, it is deliberate that we die if we have a NULL pointer
* here - anonymous is "", not NULL, which is 'never specified,
diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h
index 3e84db52a5..81773aa70a 100644
--- a/source4/auth/credentials/credentials.h
+++ b/source4/auth/credentials/credentials.h
@@ -47,9 +47,10 @@ struct cli_credentials {
enum credentials_obtained domain_obtained;
enum credentials_obtained realm_obtained;
enum credentials_obtained ccache_obtained;
- enum credentials_obtained gss_creds_obtained;
+ enum credentials_obtained client_gss_creds_obtained;
enum credentials_obtained principal_obtained;
enum credentials_obtained keytab_obtained;
+ enum credentials_obtained server_gss_creds_obtained;
const char *workstation;
const char *username;
@@ -63,8 +64,9 @@ struct cli_credentials {
struct samr_Password *nt_hash;
struct ccache_container *ccache;
- struct gssapi_creds_container *gssapi_creds;
+ struct gssapi_creds_container *client_gss_creds;
struct keytab_container *keytab;
+ struct gssapi_creds_container *server_gss_creds;
const char *(*workstation_cb) (struct cli_credentials *);
const char *(*password_cb) (struct cli_credentials *);
diff --git a/source4/auth/credentials/credentials_files.c b/source4/auth/credentials/credentials_files.c
index 35bbc43b34..6b3c77c4e3 100644
--- a/source4/auth/credentials/credentials_files.c
+++ b/source4/auth/credentials/credentials_files.c
@@ -164,9 +164,9 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file,
* @param cred Credentials structure to fill in
* @retval NTSTATUS error detailing any failure
*/
-static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
- const char *base,
- const char *filter)
+NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
+ const char *base,
+ const char *filter)
{
TALLOC_CTX *mem_ctx;
@@ -183,6 +183,8 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
"ntPwdHash",
"msDS-KeyVersionNumber",
"saltPrincipal",
+ "privateKeytab",
+ "krb5Keytab",
NULL
};
@@ -193,6 +195,7 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
const char *realm;
enum netr_SchannelType sct;
const char *salt_principal;
+ const char *keytab;
/* ok, we are going to get it now, don't recurse back here */
cred->machine_account_pending = False;
@@ -201,6 +204,7 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
cred->machine_account = True;
mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");
+
/* Local secrets are stored in secrets.ldb */
ldb = secrets_db_connect(mem_ctx);
if (!ldb) {
@@ -279,7 +283,22 @@ static NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
}
cli_credentials_set_kvno(cred, ldb_msg_find_int(msgs[0], "msDS-KeyVersionNumber", 0));
-
+
+ /* If there was an external keytab specified by reference in
+ * the LDB, then use this. Otherwise we will make one up
+ * (chewing CPU time) from the password */
+ keytab = ldb_msg_find_string(msgs[0], "krb5Keytab", NULL);
+ if (keytab) {
+ cli_credentials_set_keytab(cred, keytab, CRED_SPECIFIED);
+ } else {
+ keytab = ldb_msg_find_string(msgs[0], "privateKeytab", NULL);
+ if (keytab) {
+ keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, keytab));
+ if (keytab) {
+ cli_credentials_set_keytab(cred, keytab, CRED_SPECIFIED);
+ }
+ }
+ }
talloc_free(mem_ctx);
return NT_STATUS_OK;
@@ -345,3 +364,68 @@ void cli_credentials_set_machine_account_pending(struct cli_credentials *cred)
cred->machine_account_pending = True;
}
+
+NTSTATUS cli_credentials_update_all_keytabs(TALLOC_CTX *parent_ctx)
+{
+ TALLOC_CTX *mem_ctx;
+ int ldb_ret;
+ struct ldb_context *ldb;
+ struct ldb_message **msgs;
+ const char *attrs[] = { NULL };
+ struct cli_credentials *creds;
+ const char *filter;
+ NTSTATUS status;
+ int i, ret;
+
+ mem_ctx = talloc_new(parent_ctx);
+ if (!mem_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Local secrets are stored in secrets.ldb */
+ ldb = secrets_db_connect(mem_ctx);
+ if (!ldb) {
+ DEBUG(1, ("Could not open secrets.ldb\n"));
+ talloc_free(mem_ctx);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /* search for the secret record */
+ ldb_ret = gendb_search(ldb,
+ mem_ctx, NULL,
+ &msgs, attrs,
+ "objectClass=kerberosSecret");
+ if (ldb_ret == -1) {
+ DEBUG(1, ("Error looking for kerberos type secrets to push into a keytab"));
+ talloc_free(mem_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ for (i=0; i < ldb_ret; i++) {
+ /* Make a credentials structure from it */
+ creds = cli_credentials_init(mem_ctx);
+ if (!creds) {
+ DEBUG(1, ("cli_credentials_init failed!"));
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ cli_credentials_set_conf(creds);
+ filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_linearize(mem_ctx, msgs[i]->dn));
+ status = cli_credentials_set_secrets(creds, NULL, filter);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to read secrets for keytab update for %s\n",
+ filter));
+ talloc_free(mem_ctx);
+ return status;
+ }
+ ret = cli_credentials_update_keytab(creds);
+ if (ret != 0) {
+ DEBUG(1, ("Failed to update keytab for %s\n",
+ filter));
+ talloc_free(mem_ctx);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
index a3761e8359..173739e9b8 100644
--- a/source4/auth/credentials/credentials_krb5.c
+++ b/source4/auth/credentials/credentials_krb5.c
@@ -52,6 +52,10 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred,
char *name;
char **realm;
+ if (cred->ccache_obtained > obtained) {
+ return 0;
+ }
+
ret = krb5_cc_get_principal(cred->ccache->smb_krb5_context->krb5_context,
cred->ccache->ccache, &princ);
@@ -107,7 +111,12 @@ int cli_credentials_set_ccache(struct cli_credentials *cred,
{
krb5_error_code ret;
krb5_principal princ;
- struct ccache_container *ccc = talloc(cred, struct ccache_container);
+ struct ccache_container *ccc;
+ if (cred->ccache_obtained > obtained) {
+ return 0;
+ }
+
+ ccc = talloc(cred, struct ccache_container);
if (!ccc) {
return ENOMEM;
}
@@ -265,10 +274,10 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
OM_uint32 maj_stat, min_stat;
struct gssapi_creds_container *gcc;
struct ccache_container *ccache;
- if (cred->gss_creds_obtained >= (MAX(cred->ccache_obtained,
+ if (cred->client_gss_creds_obtained >= (MAX(cred->ccache_obtained,
MAX(cred->principal_obtained,
cred->username_obtained)))) {
- *_gcc = cred->gssapi_creds;
+ *_gcc = cred->client_gss_creds;
return 0;
}
ret = cli_credentials_get_ccache(cred,
@@ -283,8 +292,8 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
return ENOMEM;
}
- maj_stat = gss_krb5_import_ccache(&min_stat, ccache->ccache,
- &gcc->creds);
+ maj_stat = gss_krb5_import_cred(&min_stat, ccache->ccache, NULL, NULL,
+ &gcc->creds);
if (maj_stat) {
if (min_stat) {
ret = min_stat;
@@ -293,20 +302,20 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
}
}
if (ret == 0) {
- cred->gss_creds_obtained = cred->ccache_obtained;
+ cred->client_gss_creds_obtained = cred->ccache_obtained;
talloc_set_destructor(gcc, free_gssapi_creds);
- cred->gssapi_creds = gcc;
+ cred->client_gss_creds = gcc;
*_gcc = gcc;
}
return ret;
}
/**
- Set a gssapi cred_id_t into the credentails system.
+ Set a gssapi cred_id_t into the credentails system. (Client case)
This grabs the credentials both 'intact' and getting the krb5
ccache out of it. This routine can be generalised in future for
- the case where we deal with GSSAPI mechs other than krb5.
+ the case where we deal with GSSAPI mechs other than krb5.
On sucess, the caller must not free gssapi_cred, as it now belongs
to the credentials system.
@@ -319,7 +328,12 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
int ret;
OM_uint32 maj_stat, min_stat;
struct ccache_container *ccc;
- struct gssapi_creds_container *gcc = talloc(cred, struct gssapi_creds_container);
+ struct gssapi_creds_container *gcc;
+ if (cred->client_gss_creds_obtained > obtained) {
+ return 0;
+ }
+
+ gcc = talloc(cred, struct gssapi_creds_container);
if (!gcc) {
return ENOMEM;
}
@@ -346,18 +360,23 @@ int cli_credentials_get_client_gss_creds(struct cli_credentials *cred,
gcc->creds = gssapi_cred;
talloc_set_destructor(gcc, free_gssapi_creds);
- cred->gss_creds_obtained = obtained;
- cred->gssapi_creds = gcc;
+ cred->client_gss_creds_obtained = obtained;
+ cred->client_gss_creds = gcc;
}
return ret;
}
+/* Get the keytab (actually, a container containing the krb5_keytab)
+ * attached to this context. If this hasn't been done or set before,
+ * it will be generated from the password.
+ */
int cli_credentials_get_keytab(struct cli_credentials *cred,
struct keytab_container **_ktc)
{
krb5_error_code ret;
struct keytab_container *ktc;
struct smb_krb5_context *smb_krb5_context;
+ TALLOC_CTX *mem_ctx;
if (cred->keytab_obtained >= (MAX(cred->principal_obtained,
cred->username_obtained))) {
@@ -374,16 +393,180 @@ int cli_credentials_get_keytab(struct cli_credentials *cred,
return ret;
}
- ret = create_memory_keytab(cred, cred, smb_krb5_context, &ktc);
+ mem_ctx = talloc_new(cred);
+ if (!mem_ctx) {
+ return ENOMEM;
+ }
+
+ ret = create_memory_keytab(mem_ctx, cred, smb_krb5_context, &ktc);
if (ret) {
+ talloc_free(mem_ctx);
return ret;
}
cred->keytab_obtained = (MAX(cred->principal_obtained,
cred->username_obtained));
+ talloc_steal(cred, ktc);
cred->keytab = ktc;
*_ktc = cred->keytab;
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+/* Given the name of a keytab (presumably in the format
+ * FILE:/etc/krb5.keytab), open it and attach it */
+
+int cli_credentials_set_keytab(struct cli_credentials *cred,
+ const char *keytab_name,
+ enum credentials_obtained obtained)
+{
+ krb5_error_code ret;
+ struct keytab_container *ktc;
+ struct smb_krb5_context *smb_krb5_context;
+ krb5_keytab keytab;
+ TALLOC_CTX *mem_ctx;
+
+ if (cred->keytab_obtained >= obtained) {
+ return 0;
+ }
+
+ ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+ if (ret) {
+ return ret;
+ }
+
+ mem_ctx = talloc_new(cred);
+ if (!mem_ctx) {
+ return ENOMEM;
+ }
+
+ ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab);
+ if (ret) {
+ DEBUG(1,("failed to open krb5 keytab: %s\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ ktc = talloc(mem_ctx, struct keytab_container);
+ if (!ktc) {
+ talloc_free(mem_ctx);
+ return ENOMEM;
+ }
+
+ ktc->smb_krb5_context = talloc_reference(ktc, smb_krb5_context);
+ ktc->keytab = keytab;
+
+ cred->keytab_obtained = obtained;
+
+ talloc_steal(cred, ktc);
+ cred->keytab = ktc;
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
+int cli_credentials_update_keytab(struct cli_credentials *cred)
+{
+ krb5_error_code ret;
+ struct keytab_container *ktc;
+ struct smb_krb5_context *smb_krb5_context;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(cred);
+ if (!mem_ctx) {
+ return ENOMEM;
+ }
+
+ ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+ if (ret) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ ret = cli_credentials_get_keytab(cred, &ktc);
+ if (ret != 0) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ ret = update_keytab(mem_ctx, cred, smb_krb5_context, ktc);
+
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+/* Get server gss credentials (in gsskrb5, this means the keytab) */
+
+int cli_credentials_get_server_gss_creds(struct cli_credentials *cred,
+ struct gssapi_creds_container **_gcc)
+{
+ int ret = 0;
+ OM_uint32 maj_stat, min_stat;
+ struct gssapi_creds_container *gcc;
+ struct keytab_container *ktc;
+ struct smb_krb5_context *smb_krb5_context;
+ TALLOC_CTX *mem_ctx;
+ krb5_principal princ;
+
+ if (cred->server_gss_creds_obtained >= (MAX(cred->keytab_obtained,
+ MAX(cred->principal_obtained,
+ cred->username_obtained)))) {
+ *_gcc = cred->server_gss_creds;
+ return 0;
+ }
+
+ ret = cli_credentials_get_krb5_context(cred, &smb_krb5_context);
+ if (ret) {
+ return ret;
+ }
+
+ ret = cli_credentials_get_keytab(cred,
+ &ktc);
+ if (ret) {
+ DEBUG(1, ("Failed to get keytab for GSSAPI server: %s\n", error_message(ret)));
+ return ret;
+ }
+
+ mem_ctx = talloc_new(cred);
+ if (!mem_ctx) {
+ return ENOMEM;
+ }
+
+ ret = principal_from_credentials(mem_ctx, cred, smb_krb5_context, &princ);
+ if (ret) {
+ DEBUG(1,("cli_credentials_get_server_gss_creds: makeing krb5 principal failed (%s)\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ gcc = talloc(cred, struct gssapi_creds_container);
+ if (!gcc) {
+ talloc_free(mem_ctx);
+ return ENOMEM;
+ }
+
+ /* This creates a GSSAPI cred_id_t with the principal and keytab set */
+ maj_stat = gss_krb5_import_cred(&min_stat, NULL, princ, ktc->keytab,
+ &gcc->creds);
+ if (maj_stat) {
+ if (min_stat) {
+ ret = min_stat;
+ } else {
+ ret = EINVAL;
+ }
+ }
+ if (ret == 0) {
+ cred->server_gss_creds_obtained = cred->keytab_obtained;
+ talloc_set_destructor(gcc, free_gssapi_creds);
+ cred->server_gss_creds = gcc;
+ *_gcc = gcc;
+ }
+ talloc_free(mem_ctx);
return ret;
}
@@ -415,3 +598,5 @@ void cli_credentials_set_salt_principal(struct cli_credentials *cred, const char
{
cred->salt_principal = talloc_strdup(cred, principal);
}
+
+
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index b5a2dadd35..68da2567da 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -41,12 +41,9 @@ struct gensec_gssapi_state {
DATA_BLOB pac;
struct smb_krb5_context *smb_krb5_context;
- krb5_ccache ccache;
- const char *ccache_name;
- struct keytab_container *keytab;
struct gssapi_creds_container *client_cred;
+ struct gssapi_creds_container *server_cred;
- gss_cred_id_t cred;
gss_cred_id_t delegated_cred_handle;
};
@@ -81,10 +78,6 @@ static int gensec_gssapi_destory(void *ptr)
struct gensec_gssapi_state *gensec_gssapi_state = ptr;
OM_uint32 maj_stat, min_stat;
- if (gensec_gssapi_state->cred != GSS_C_NO_CREDENTIAL) {
- maj_stat = gss_release_cred(&min_stat,
- &gensec_gssapi_state->cred);
- }
if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
maj_stat = gss_release_cred(&min_stat,
&gensec_gssapi_state->delegated_cred_handle);
@@ -137,7 +130,6 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
gensec_gssapi_state->session_key = data_blob(NULL, 0);
gensec_gssapi_state->pac = data_blob(NULL, 0);
- gensec_gssapi_state->cred = GSS_C_NO_CREDENTIAL;
gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destory);
@@ -167,11 +159,10 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
{
NTSTATUS nt_status;
- OM_uint32 maj_stat, min_stat;
int ret;
- const char *principal;
struct gensec_gssapi_state *gensec_gssapi_state;
struct cli_credentials *machine_account;
+ struct gssapi_creds_container *gcc;
nt_status = gensec_gssapi_start(gensec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -186,53 +177,15 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
DEBUG(3, ("No machine account credentials specified\n"));
return NT_STATUS_INVALID_PARAMETER;
} else {
- ret = cli_credentials_get_keytab(machine_account, &gensec_gssapi_state->keytab);
+ ret = cli_credentials_get_server_gss_creds(machine_account, &gcc);
if (ret) {
- DEBUG(3, ("Could not create memory keytab!\n"));
+ DEBUG(1, ("Aquiring acceptor credentials failed: %s\n",
+ error_message(ret)));
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
}
- principal = cli_credentials_get_principal(machine_account,
- machine_account);
-
- /* This might have been explicity set to NULL, ie use what the client calls us */
- if (principal) {
- gss_buffer_desc name_token;
-
- name_token.value = discard_const_p(uint8_t, principal);
- name_token.length = strlen(principal);
-
- maj_stat = gss_import_name (&min_stat,
- &name_token,
- GSS_C_NT_USER_NAME,
- &gensec_gssapi_state->server_name);
-
- if (maj_stat) {
- DEBUG(2, ("GSS Import name of %s failed: %s\n",
- (char *)name_token.value,
- gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
- return NT_STATUS_UNSUCCESSFUL;
- }
- } else {
- gensec_gssapi_state->server_name = GSS_C_NO_NAME;
- }
-
- maj_stat = gsskrb5_acquire_cred(&min_stat,
- gensec_gssapi_state->keytab->keytab,
- gensec_gssapi_state->server_name,
- GSS_C_INDEFINITE,
- GSS_C_NULL_OID_SET,
- GSS_C_ACCEPT,
- &gensec_gssapi_state->cred,
- NULL,
- NULL);
- if (maj_stat) {
- DEBUG(1, ("Aquiring acceptor credentails failed: %s\n",
- gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat)));
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
-
+ gensec_gssapi_state->server_cred = gcc;
return NT_STATUS_OK;
}
@@ -382,7 +335,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
{
maj_stat = gss_accept_sec_context(&min_stat,
&gensec_gssapi_state->gssapi_context,
- gensec_gssapi_state->cred,
+ gensec_gssapi_state->server_cred->creds,
&input_token,
gensec_gssapi_state->input_chan_bindings,
&gensec_gssapi_state->client_name,
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c
index 565c7478f9..6f6203a92c 100644
--- a/source4/heimdal/kdc/kerberos5.c
+++ b/source4/heimdal/kdc/kerberos5.c
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
+RCSID("$Id: kerberos5.c,v 1.198 2005/11/28 20:33:57 lha Exp $");
#define MAX_TIME ((time_t)((1U << 31) - 1))
@@ -666,8 +666,7 @@ _kdc_check_flags(krb5_context context,
starttime_str, sizeof(starttime_str), TRUE);
kdc_log(context, config, 0,
"Client not yet valid until %s -- %s",
- starttime_str,
- client_name);
+ starttime_str, client_name);
return KRB5KDC_ERR_CLIENT_NOTYET;
}
@@ -676,7 +675,8 @@ _kdc_check_flags(krb5_context context,
krb5_format_time(context, *client->valid_end,
endtime_str, sizeof(endtime_str), TRUE);
kdc_log(context, config, 0,
- "Client expired at %s -- %s", endtime_str, client_name);
+ "Client expired at %s -- %s",
+ endtime_str, client_name);
return KRB5KDC_ERR_NAME_EXP;
}
@@ -686,7 +686,8 @@ _kdc_check_flags(krb5_context context,
krb5_format_time(context, *client->pw_end,
pwend_str, sizeof(pwend_str), TRUE);
kdc_log(context, config, 0,
- "Client's key has expired at %s -- %s", pwend_str, client_name);
+ "Client's key has expired at %s -- %s",
+ pwend_str, client_name);
return KRB5KDC_ERR_KEY_EXPIRED;
}
}
@@ -717,7 +718,8 @@ _kdc_check_flags(krb5_context context,
krb5_format_time(context, *server->valid_start,
starttime_str, sizeof(starttime_str), TRUE);
kdc_log(context, config, 0,
- "Server not yet valid until %s -- %s", server_name);
+ "Server not yet valid until %s -- %s",
+ starttime_str, server_name);
return KRB5KDC_ERR_SERVICE_NOTYET;
}
@@ -1099,11 +1101,12 @@ _kdc_as_rep(krb5_context context,
pa->padata_value.data = NULL;
#endif
- /* RFC4120 requires:
- - If the client only knows about old enctypes, then send both info replies
- (we send 'info' first in the list).
- - If the client is 'modern', because it knows about 'new' enc types, then
- only send the 'info2' reply.
+ /*
+ * RFC4120 requires:
+ * - If the client only knows about old enctypes, then send
+ * both info replies (we send 'info' first in the list).
+ * - If the client is 'modern', because it knows about 'new'
+ * enctype types, then only send the 'info2' reply.
*/
/* XXX check ret */
if (only_older_enctype_p(req))
diff --git a/source4/heimdal/lib/gssapi/accept_sec_context.c b/source4/heimdal/lib/gssapi/accept_sec_context.c
index 5d43cdcb43..9ca60a6cdd 100644
--- a/source4/heimdal/lib/gssapi/accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/accept_sec_context.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: accept_sec_context.c,v 1.53 2005/05/29 15:12:41 lha Exp $");
+RCSID("$Id: accept_sec_context.c,v 1.55 2005/11/25 15:57:35 lha Exp $");
HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;
krb5_keytab gssapi_krb5_keytab;
@@ -125,66 +125,24 @@ gsskrb5_accept_delegated_token
krb5_principal principal = (*context_handle)->source;
krb5_ccache ccache = NULL;
krb5_error_code kret;
- int32_t ac_flags, ret;
- gss_cred_id_t handle = NULL;
+ int32_t ac_flags, ret = GSS_S_COMPLETE;
- if (delegated_cred_handle == NULL) {
- /* XXX Create a new delegated_cred_handle? */
-
- ret = 0;
+ *minor_status = 0;
+ /* XXX Create a new delegated_cred_handle? */
+ if (delegated_cred_handle == NULL)
kret = krb5_cc_default (gssapi_krb5_context, &ccache);
- if (kret) {
- *flags &= ~GSS_C_DELEG_FLAG;
- goto end_fwd;
- }
- } else {
-
- *delegated_cred_handle = NULL;
-
- handle = calloc(1, sizeof(*handle));
- if (handle == NULL) {
- ret = GSS_S_FAILURE;
- *minor_status = ENOMEM;
- krb5_set_error_string(gssapi_krb5_context, "out of memory");
- gssapi_krb5_set_error_string();
- *flags &= ~GSS_C_DELEG_FLAG;
- goto end_fwd;
- }
- if ((ret = gss_duplicate_name(minor_status, principal,
- &handle->principal)) != 0) {
- *flags &= ~GSS_C_DELEG_FLAG;
- ret = 0;
- goto end_fwd;
- }
- kret = krb5_cc_gen_new (gssapi_krb5_context,
- &krb5_mcc_ops,
- &handle->ccache);
- if (kret) {
- *flags &= ~GSS_C_DELEG_FLAG;
- ret = 0;
- goto end_fwd;
- }
- ccache = handle->ccache;
-
- ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
- if (ret) {
- *flags &= ~GSS_C_DELEG_FLAG;
- goto end_fwd;
- }
- ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
- &handle->mechanisms);
- if (ret) {
- *flags &= ~GSS_C_DELEG_FLAG;
- goto end_fwd;
- }
+ else
+ kret = krb5_cc_gen_new (gssapi_krb5_context, &krb5_mcc_ops, &ccache);
+ if (kret) {
+ *flags &= ~GSS_C_DELEG_FLAG;
+ goto out;
}
kret = krb5_cc_initialize(gssapi_krb5_context, ccache, principal);
if (kret) {
*flags &= ~GSS_C_DELEG_FLAG;
- ret = 0;
- goto end_fwd;
+ goto out;
}
krb5_auth_con_removeflags(gssapi_krb5_context,
@@ -204,29 +162,29 @@ gsskrb5_accept_delegated_token
*flags &= ~GSS_C_DELEG_FLAG;
ret = GSS_S_FAILURE;
*minor_status = kret;
- goto end_fwd;
+ goto out;
}
- end_fwd:
- /* if there was some kind of failure, clean up internal structures */
- if ((*flags & GSS_C_DELEG_FLAG) == 0) {
- if (handle) {
- if (handle->principal)
- gss_release_name(minor_status, &handle->principal);
- if (handle->mechanisms)
- gss_release_oid_set(NULL, &handle->mechanisms);
- if (handle->ccache)
- krb5_cc_destroy(gssapi_krb5_context, handle->ccache);
- free(handle);
- handle = NULL;
- }
+
+ if (delegated_cred_handle) {
+ ret = gss_krb5_import_cred(minor_status,
+ ccache,
+ NULL,
+ NULL,
+ delegated_cred_handle);
+ if (ret != GSS_S_COMPLETE)
+ goto out;
+
+ (*delegated_cred_handle)->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
+ ccache = NULL;
}
- if (delegated_cred_handle == NULL) {
- if (ccache)
+
+out:
+ if (ccache) {
+ if (delegated_cred_handle == NULL)
krb5_cc_close(gssapi_krb5_context, ccache);
+ else
+ krb5_cc_destroy(gssapi_krb5_context, ccache);
}
- if (handle)
- *delegated_cred_handle = handle;
-
return ret;
}
@@ -1054,7 +1012,7 @@ spnego_accept_sec_context
if(len > data.length - taglen)
return ASN1_OVERRUN;
- ret = decode_NegTokenInit((const char *)data.data + taglen, len,
+ ret = decode_NegTokenInit((const unsigned char *)data.data + taglen, len,
&ni, &ni_len);
if (ret)
return GSS_S_DEFECTIVE_TOKEN;
@@ -1065,7 +1023,7 @@ spnego_accept_sec_context
}
for (i = 0; !found && i < ni.mechTypes->len; ++i) {
- char mechbuf[17];
+ unsigned char mechbuf[17];
size_t mech_len;
ret = der_put_oid (mechbuf + sizeof(mechbuf) - 1,
diff --git a/source4/heimdal/lib/gssapi/acquire_cred.c b/source4/heimdal/lib/gssapi/acquire_cred.c
index d67b400920..44dbef3c48 100644
--- a/source4/heimdal/lib/gssapi/acquire_cred.c
+++ b/source4/heimdal/lib/gssapi/acquire_cred.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: acquire_cred.c,v 1.24 2005/10/26 11:25:16 lha Exp $");
+RCSID("$Id: acquire_cred.c,v 1.25 2005/11/02 08:56:25 lha Exp $");
OM_uint32
_gssapi_krb5_ccache_lifetime(OM_uint32 *minor_status,
@@ -106,7 +106,6 @@ get_keytab(krb5_context context, krb5_keytab *keytab)
static OM_uint32 acquire_initiator_cred
(OM_uint32 * minor_status,
krb5_context context,
- krb5_keytab keytab,
const gss_name_t desired_name,
OM_uint32 time_req,
const gss_OID_set desired_mechs,
@@ -122,7 +121,7 @@ static OM_uint32 acquire_initiator_cred
krb5_get_init_creds_opt *opt;
krb5_ccache ccache;
krb5_error_code kret;
- krb5_boolean made_keytab = FALSE;
+ krb5_keytab keytab;
ccache = NULL;
def_princ = NULL;
@@ -214,7 +213,7 @@ end:
krb5_free_cred_contents(context, &cred);
if (def_princ != NULL)
krb5_free_principal(context, def_princ);
- if (made_keytab)
+ if (keytab != NULL)
krb5_kt_close(context, keytab);
if (ret != GSS_S_COMPLETE) {
if (ccache != NULL)
@@ -230,7 +229,6 @@ end:
static OM_uint32 acquire_acceptor_cred
(OM_uint32 * minor_status,
krb5_context context,
- krb5_keytab keytab,
OM_uint32 time_req,
const gss_OID_set desired_mechs,
gss_cred_usage_t cred_usage,
@@ -244,21 +242,14 @@ static OM_uint32 acquire_acceptor_cred
kret = 0;
ret = GSS_S_FAILURE;
- if (keytab == NULL) {
- kret = get_keytab(context, &handle->keytab);
- if (kret)
- goto end;
- handle->made_keytab = TRUE;
- } else {
- handle->keytab = keytab;
- handle->made_keytab = FALSE;
- }
+ kret = get_keytab(context, &handle->keytab);
+ if (kret)
+ goto end;
ret = GSS_S_COMPLETE;
end:
if (ret != GSS_S_COMPLETE) {
- if (handle->made_keytab)
- krb5_kt_close(context, handle->keytab);
+ krb5_kt_close(context, handle->keytab);
if (kret != 0) {
*minor_status = kret;
gssapi_krb5_set_error_string ();
@@ -267,9 +258,8 @@ end:
return (ret);
}
-OM_uint32 gsskrb5_acquire_cred
+OM_uint32 gss_acquire_cred
(OM_uint32 * minor_status,
- struct krb5_keytab_data *keytab,
const gss_name_t desired_name,
OM_uint32 time_req,
const gss_OID_set desired_mechs,
@@ -328,7 +318,6 @@ OM_uint32 gsskrb5_acquire_cred
}
if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {
ret = acquire_initiator_cred(minor_status, gssapi_krb5_context,
- keytab,
desired_name, time_req,
desired_mechs, cred_usage,
handle, actual_mechs, time_rec);
@@ -341,7 +330,7 @@ OM_uint32 gsskrb5_acquire_cred
}
if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) {
ret = acquire_acceptor_cred(minor_status, gssapi_krb5_context,
- keytab, time_req,
+ time_req,
desired_mechs, cred_usage,
handle, actual_mechs, time_rec);
if (ret != GSS_S_COMPLETE) {
@@ -381,24 +370,3 @@ OM_uint32 gsskrb5_acquire_cred
return (GSS_S_COMPLETE);
}
-OM_uint32 gss_acquire_cred
- (OM_uint32 * minor_status,
- const gss_name_t desired_name,
- OM_uint32 time_req,
- const gss_OID_set desired_mechs,
- gss_cred_usage_t cred_usage,
- gss_cred_id_t * output_cred_handle,
- gss_OID_set * actual_mechs,
- OM_uint32 * time_rec
- )
-{
- return gsskrb5_acquire_cred(minor_status,
- NULL,
- desired_name,
- time_req,
- desired_mechs,
- cred_usage,
- output_cred_handle,
- actual_mechs,
- time_rec);
-}
diff --git a/source4/heimdal/lib/gssapi/arcfour.c b/source4/heimdal/lib/gssapi/arcfour.c
index 52bb2ecf1b..01c6c75ecc 100644
--- a/source4/heimdal/lib/gssapi/arcfour.c
+++ b/source4/heimdal/lib/gssapi/arcfour.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 - 2004 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: arcfour.c,v 1.17 2005/05/06 07:13:32 lha Exp $");
+RCSID("$Id: arcfour.c,v 1.18 2005/11/01 06:55:55 lha Exp $");
/*
* Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
@@ -105,7 +105,7 @@ arcfour_mic_key(krb5_context context, krb5_keyblock *key,
static krb5_error_code
arcfour_mic_cksum(krb5_keyblock *key, unsigned usage,
u_char *sgn_cksum, size_t sgn_cksum_sz,
- const char *v1, size_t l1,
+ const u_char *v1, size_t l1,
const void *v2, size_t l2,
const void *v3, size_t l3)
{
@@ -256,7 +256,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
p = token_buffer->value;
omret = gssapi_krb5_verify_header (&p,
token_buffer->length,
- type,
+ (u_char *)type,
GSS_KRB5_MECHANISM);
if (omret)
return omret;
diff --git a/source4/heimdal/lib/gssapi/copy_ccache.c b/source4/heimdal/lib/gssapi/copy_ccache.c
index 0f2f155870..782b701e44 100644
--- a/source4/heimdal/lib/gssapi/copy_ccache.c
+++ b/source4/heimdal/lib/gssapi/copy_ccache.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000 - 2001, 2003 Kungliga Tekniska Högskolan
+ * Copyright (c) 2000 - 2001, 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: copy_ccache.c,v 1.9 2005/10/31 16:02:08 lha Exp $");
+RCSID("$Id: copy_ccache.c,v 1.13 2005/11/28 23:05:44 lha Exp $");
OM_uint32
gss_krb5_copy_ccache(OM_uint32 *minor_status,
@@ -63,9 +63,11 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status,
OM_uint32
-gss_krb5_import_ccache(OM_uint32 *minor_status,
- krb5_ccache in,
- gss_cred_id_t *cred)
+gss_krb5_import_cred(OM_uint32 *minor_status,
+ krb5_ccache id,
+ krb5_principal keytab_principal,
+ krb5_keytab keytab,
+ gss_cred_id_t *cred)
{
krb5_error_code kret;
gss_cred_id_t handle;
@@ -83,57 +85,94 @@ gss_krb5_import_ccache(OM_uint32 *minor_status,
}
HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
- handle->usage = GSS_C_INITIATE;
+ handle->usage = 0;
- kret = krb5_cc_get_principal(gssapi_krb5_context, in, &handle->principal);
- if (kret) {
- free(handle);
- gssapi_krb5_set_error_string ();
- *minor_status = kret;
- return GSS_S_FAILURE;
- }
+ if (id) {
+ char *str;
- ret = _gssapi_krb5_ccache_lifetime(minor_status,
- in,
- handle->principal,
- &handle->lifetime);
- if (ret != GSS_S_COMPLETE) {
- krb5_free_principal(gssapi_krb5_context, handle->principal);
- free(handle);
- return ret;
- }
+ handle->usage |= GSS_C_INITIATE;
- ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
- if (ret == GSS_S_COMPLETE)
- ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
- &handle->mechanisms);
- if (ret != GSS_S_COMPLETE) {
- krb5_free_principal(gssapi_krb5_context, handle->principal);
- free(handle);
- *minor_status = kret;
- return GSS_S_FAILURE;
+ kret = krb5_cc_get_principal(gssapi_krb5_context, id,
+ &handle->principal);
+ if (kret) {
+ free(handle);
+ gssapi_krb5_set_error_string ();
+ *minor_status = kret;
+ return GSS_S_FAILURE;
+ }
+
+ if (keytab_principal) {
+ krb5_boolean match;
+
+ match = krb5_principal_compare(gssapi_krb5_context,
+ handle->principal,
+ keytab_principal);
+ if (match == FALSE) {
+ krb5_free_principal(gssapi_krb5_context, handle->principal);
+ free(handle);
+ gssapi_krb5_clear_status ();
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+ }
+
+ ret = _gssapi_krb5_ccache_lifetime(minor_status,
+ id,
+ handle->principal,
+ &handle->lifetime);
+ if (ret != GSS_S_COMPLETE) {
+ krb5_free_principal(gssapi_krb5_context, handle->principal);
+ free(handle);
+ return ret;
+ }
+
+
+ kret = krb5_cc_get_full_name(gssapi_krb5_context, id, &str);
+ if (kret)
+ goto out;
+
+ kret = krb5_cc_resolve(gssapi_krb5_context, str, &handle->ccache);
+ free(str);
+ if (kret)
+ goto out;
}
- {
- const char *type, *name;
+
+ if (keytab) {
char *str;
- type = krb5_cc_get_type(gssapi_krb5_context, in);
- name = krb5_cc_get_name(gssapi_krb5_context, in);
-
- if (asprintf(&str, "%s:%s", type, name) == -1) {
- krb5_set_error_string(gssapi_krb5_context,
- "malloc - out of memory");
- kret = ENOMEM;
- goto out;
+ handle->usage |= GSS_C_ACCEPT;
+
+ if (keytab_principal && handle->principal == NULL) {
+ kret = krb5_copy_principal(gssapi_krb5_context,
+ keytab_principal,
+ &handle->principal);
+ if (kret)
+ goto out;
}
- kret = krb5_cc_resolve(gssapi_krb5_context, str, &handle->ccache);
+ kret = krb5_kt_get_full_name(gssapi_krb5_context, keytab, &str);
+ if (kret)
+ goto out;
+
+ kret = krb5_kt_resolve(gssapi_krb5_context, str, &handle->keytab);
free(str);
if (kret)
goto out;
}
+
+ if (id || keytab) {
+ ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
+ if (ret == GSS_S_COMPLETE)
+ ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
+ &handle->mechanisms);
+ if (ret != GSS_S_COMPLETE) {
+ kret = *minor_status;
+ goto out;
+ }
+ }
+
*minor_status = 0;
*cred = handle;
return GSS_S_COMPLETE;
diff --git a/source4/heimdal/lib/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi.h
index 64a31d1eee..20700dc826 100644
--- a/source4/heimdal/lib/gssapi/gssapi.h
+++ b/source4/heimdal/lib/gssapi/gssapi.h
@@ -775,18 +775,6 @@ OM_uint32 gss_unseal
* kerberos mechanism specific functions
*/
-OM_uint32 gsskrb5_acquire_cred
- (OM_uint32 * minor_status,
- struct krb5_keytab_data *keytab,
- const gss_name_t desired_name,
- OM_uint32 time_req,
- const gss_OID_set desired_mechs,
- gss_cred_usage_t cred_usage,
- gss_cred_id_t * output_cred_handle,
- gss_OID_set * actual_mechs,
- OM_uint32 * time_rec
- );
-
OM_uint32
gss_krb5_ccache_name(OM_uint32 * /*minor_status*/,
const char * /*name */,
@@ -805,10 +793,11 @@ OM_uint32 gss_krb5_copy_service_keyblock
gss_ctx_id_t context_handle,
struct EncryptionKey **out);
-OM_uint32
-gss_krb5_import_ccache(OM_uint32 */*minor*/,
- struct krb5_ccache_data * /*in*/,
- gss_cred_id_t */*out*/);
+OM_uint32 gss_krb5_import_cred(OM_uint32 *minor_status,
+ struct krb5_ccache_data * /* id */,
+ struct Principal * /* keytab_principal */,
+ struct krb5_keytab_data * /* keytab */,
+ gss_cred_id_t */* cred */);
OM_uint32 gss_krb5_get_tkt_flags
(OM_uint32 */*minor*/,
diff --git a/source4/heimdal/lib/gssapi/gssapi_locl.h b/source4/heimdal/lib/gssapi/gssapi_locl.h
index ae291d15a9..b9bea7db2e 100644
--- a/source4/heimdal/lib/gssapi/gssapi_locl.h
+++ b/source4/heimdal/lib/gssapi/gssapi_locl.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: gssapi_locl.h,v 1.42 2005/10/26 11:23:48 lha Exp $ */
+/* $Id: gssapi_locl.h,v 1.43 2005/11/02 08:51:17 lha Exp $ */
#ifndef GSSAPI_LOCL_H
#define GSSAPI_LOCL_H
diff --git a/source4/heimdal/lib/gssapi/init_sec_context.c b/source4/heimdal/lib/gssapi/init_sec_context.c
index e7e8f5153e..61c020b800 100644
--- a/source4/heimdal/lib/gssapi/init_sec_context.c
+++ b/source4/heimdal/lib/gssapi/init_sec_context.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: init_sec_context.c,v 1.60 2005/10/12 07:25:18 lha Exp $");
+RCSID("$Id: init_sec_context.c,v 1.61 2005/11/02 11:52:49 lha Exp $");
/*
* copy the addresses from `input_chan_bindings' (if any) to
diff --git a/source4/heimdal/lib/gssapi/release_cred.c b/source4/heimdal/lib/gssapi/release_cred.c
index ddd80c144b..cca3dfe379 100644
--- a/source4/heimdal/lib/gssapi/release_cred.c
+++ b/source4/heimdal/lib/gssapi/release_cred.c
@@ -33,7 +33,7 @@
#include "gssapi_locl.h"
-RCSID("$Id: release_cred.c,v 1.10 2003/10/07 00:51:46 lha Exp $");
+RCSID("$Id: release_cred.c,v 1.11 2005/11/02 08:57:35 lha Exp $");
OM_uint32 gss_release_cred
(OM_uint32 * minor_status,
diff --git a/source4/heimdal/lib/hdb/db.c b/source4/heimdal/lib/hdb/db.c
index d7a4cf35ee..b9f1ab47e1 100644
--- a/source4/heimdal/lib/hdb/db.c
+++ b/source4/heimdal/lib/hdb/db.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "hdb_locl.h"
-RCSID("$Id: db.c,v 1.32 2005/06/23 13:34:17 lha Exp $");
+RCSID("$Id: db.c,v 1.33 2005/11/28 23:30:51 lha Exp $");
#if HAVE_DB1
@@ -270,7 +270,7 @@ krb5_error_code
hdb_db_create(krb5_context context, HDB **db,
const char *filename)
{
- *db = malloc(sizeof(**db));
+ *db = calloc(1, sizeof(**db));
if (*db == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
diff --git a/source4/heimdal/lib/hdb/hdb-protos.h b/source4/heimdal/lib/hdb/hdb-protos.h
index 7557b46bff..f7e0c54b7c 100644
--- a/source4/heimdal/lib/hdb/hdb-protos.h
+++ b/source4/heimdal/lib/hdb/hdb-protos.h
@@ -120,7 +120,9 @@ hdb_free_entry (
hdb_entry */*ent*/);
void
-hdb_free_entry_ex(krb5_context context, hdb_entry_ex *ent);
+hdb_free_entry_ex (
+ krb5_context /*context*/,
+ hdb_entry_ex */*ent*/);
void
hdb_free_key (Key */*key*/);
diff --git a/source4/heimdal/lib/hdb/ndbm.c b/source4/heimdal/lib/hdb/ndbm.c
index 588ff80728..dfd5bfa8f1 100644
--- a/source4/heimdal/lib/hdb/ndbm.c
+++ b/source4/heimdal/lib/hdb/ndbm.c
@@ -339,6 +339,8 @@ hdb_ndbm_create(krb5_context context, HDB **db,
return ENOMEM;
}
+ memset(*db, '\0', sizeof(**db));
+
(*db)->hdb_db = NULL;
(*db)->hdb_name = strdup(filename);
if ((*db)->hdb_name == NULL) {
diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c
index ec956409a7..25dc2cb8c0 100644
--- a/source4/heimdal/lib/krb5/cache.c
+++ b/source4/heimdal/lib/krb5/cache.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: cache.c,v 1.73 2005/10/19 17:30:40 lha Exp $");
+RCSID("$Id: cache.c,v 1.74 2005/11/01 09:36:41 lha Exp $");
/*
* Add a new ccache type with operations `ops', overwriting any
@@ -223,6 +223,41 @@ krb5_cc_get_type(krb5_context context,
}
/*
+ * Return the complete resolvable name the ccache `id' in `str´.
+ * `str` should be freed with free(3).
+ * Returns 0 or an error (and then *str is set to NULL).
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_full_name(krb5_context context,
+ krb5_ccache id,
+ char **str)
+{
+ const char *type, *name;
+
+ *str = NULL;
+
+ type = krb5_cc_get_type(context, id);
+ if (type == NULL) {
+ krb5_set_error_string(context, "cache have no name of type");
+ return KRB5_CC_UNKNOWN_TYPE;
+ }
+
+ name = krb5_cc_get_name(context, id);
+ if (name == NULL) {
+ krb5_set_error_string(context, "cache of type %s have no name", type);
+ return KRB5_CC_BADNAME;
+ }
+
+ if (asprintf(str, "%s:%s", type, name) == -1) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ *str = NULL;
+ return ENOMEM;
+ }
+ return 0;
+}
+
+/*
* Return krb5_cc_ops of a the ccache `id'.
*/
diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c
index 7bc8942f66..be5c1db47d 100644
--- a/source4/heimdal/lib/krb5/get_for_creds.c
+++ b/source4/heimdal/lib/krb5/get_for_creds.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: get_for_creds.c,v 1.45 2005/06/15 02:44:36 lha Exp $");
+RCSID("$Id: get_for_creds.c,v 1.46 2005/11/28 20:43:02 lha Exp $");
static krb5_error_code
add_addrs(krb5_context context,
@@ -385,17 +385,13 @@ krb5_get_forwarded_creds (krb5_context context,
cred.enc_part.cipher.data = buf;
cred.enc_part.cipher.length = buf_size;
} else {
- /*
- * RFC4120 claims we should use the session key, but Heimdal
- * before 0.8 used the remote subkey if it was send in the
- * auth_context.
- *
- * Lorikeet-Heimdal is interested in windows compatiblity
- * more than Heimdal compatability, so we must choose the
- * session key, and break forwarding credentials to older
- * Heimdal servers.
- */
-
+ /*
+ * Here older versions then 0.7.2 of Heimdal used the local or
+ * remote subkey. That is wrong, the session key should be
+ * used. Heimdal 0.7.2 and newer have code to try both in the
+ * receiving end.
+ */
+
ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
if (ret) {
free(buf);
diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c
index 23f6685049..43fc21c1d1 100644
--- a/source4/heimdal/lib/krb5/keytab.c
+++ b/source4/heimdal/lib/krb5/keytab.c
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$Id: keytab.c,v 1.62 2005/07/06 01:14:42 lha Exp $");
+RCSID("$Id: keytab.c,v 1.63 2005/11/25 21:46:40 lha Exp $");
/*
* Register a new keytab in `ops'
@@ -240,6 +240,40 @@ krb5_kt_get_name(krb5_context context,
}
/*
+ * Retrieve the full name of the keytab `keytab' and store the name in
+ * `str'. `str' needs to be freed by the caller using free(3).
+ * Returns 0 or an error. On error, *str is set to NULL.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_full_name(krb5_context context,
+ krb5_keytab keytab,
+ char **str)
+{
+ char type[KRB5_KT_PREFIX_MAX_LEN];
+ char name[MAXPATHLEN];
+ krb5_error_code ret;
+
+ *str = NULL;
+
+ ret = krb5_kt_get_type(context, keytab, type, sizeof(type));
+ if (ret)
+ return ret;
+
+ ret = krb5_kt_get_name(context, keytab, name, sizeof(name));
+ if (ret)
+ return ret;
+
+ if (asprintf(str, "%s:%s", type, name) == -1) {
+ krb5_set_error_string(context, "malloc - out of memory");
+ *str = NULL;
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+/*
* Finish using the keytab in `id'. All resources will be released,
* even on errors. Return 0 or an error.
*/
diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h
index 2645c29fe7..3602c89ec6 100644
--- a/source4/heimdal/lib/krb5/krb5-private.h
+++ b/source4/heimdal/lib/krb5/krb5-private.h
@@ -77,6 +77,15 @@ _krb5_extract_ticket (
krb5_decrypt_proc /*decrypt_proc*/,
krb5_const_pointer /*decryptarg*/);
+int
+_krb5_find_type_in_ad (
+ krb5_context /*context*/,
+ int /*type*/,
+ krb5_data */*data*/,
+ krb5_boolean */*found*/,
+ krb5_keyblock */*sessionkey*/,
+ const AuthorizationData */*ad*/);
+
void
_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/);
@@ -399,12 +408,4 @@ _krb5_xunlock (
krb5_context /*context*/,
int /*fd*/);
-int
-_krb5_find_type_in_ad(krb5_context context,
- int type,
- krb5_data *data,
- int *found,
- krb5_keyblock *sessionkey,
- const AuthorizationData *ad);
-
#endif /* __krb5_private_h__ */
diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h
index a46f8b8f8f..33e35ca60e 100644
--- a/source4/heimdal/lib/krb5/krb5-protos.h
+++ b/source4/heimdal/lib/krb5/krb5-protos.h
@@ -607,6 +607,12 @@ krb5_cc_gen_new (
const krb5_cc_ops */*ops*/,
krb5_ccache */*id*/);
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_full_name (
+ krb5_context /*context*/,
+ krb5_ccache /*id*/,
+ char **/*str*/);
+
const char* KRB5_LIB_FUNCTION
krb5_cc_get_name (
krb5_context /*context*/,
@@ -2186,6 +2192,12 @@ krb5_kt_get_entry (
krb5_keytab_entry */*entry*/);
krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_full_name (
+ krb5_context /*context*/,
+ krb5_keytab /*keytab*/,
+ char **/*str*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_get_name (
krb5_context /*context*/,
krb5_keytab /*keytab*/,
diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c
index 07f142267c..d62adadf26 100644
--- a/source4/heimdal/lib/krb5/rd_cred.c
+++ b/source4/heimdal/lib/krb5/rd_cred.c
@@ -33,7 +33,7 @@
#include <krb5_locl.h>
-RCSID("$Id: rd_cred.c,v 1.25 2005/09/23 03:37:57 lha Exp $");
+RCSID("$Id: rd_cred.c,v 1.26 2005/11/02 08:36:42 lha Exp $");
static krb5_error_code
compare_addrs(krb5_context context,
diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c
index 0eb109c2cf..1530a9f6a8 100644
--- a/source4/libnet/libnet_join.c
+++ b/source4/libnet/libnet_join.c
@@ -1094,6 +1094,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
uint32_t acct_type = 0;
const char *account_name;
const char *netbios_name;
+ char *filter;
r->out.error_string = NULL;
@@ -1212,6 +1213,13 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
talloc_free(tmp_mem);
return NT_STATUS_NO_MEMORY;
}
+
+ rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain");
+ if (rtn == -1) {
+ r->out.error_string = NULL;
+ talloc_free(tmp_mem);
+ return NT_STATUS_NO_MEMORY;
+ }
}
rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain");
@@ -1341,6 +1349,33 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx,
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
+ if (r2->out.realm) {
+ struct cli_credentials *creds;
+ /* Make a credentials structure from it */
+ creds = cli_credentials_init(mem_ctx);
+ if (!creds) {
+ r->out.error_string = NULL;
+ talloc_free(tmp_mem);
+ return NT_STATUS_NO_MEMORY;
+ }
+ cli_credentials_set_conf(creds);
+ filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_linearize(mem_ctx, msg->dn));
+ status = cli_credentials_set_secrets(creds, NULL, filter);
+ if (!NT_STATUS_IS_OK(status)) {
+ r->out.error_string = talloc_asprintf(mem_ctx, "Failed to read secrets for keytab update for %s\n",
+ filter);
+ talloc_free(tmp_mem);
+ return status;
+ }
+ ret = cli_credentials_update_keytab(creds);
+ if (ret != 0) {
+ r->out.error_string = talloc_asprintf(mem_ctx, "Failed to update keytab for %s\n",
+ filter);
+ talloc_free(tmp_mem);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
/* move all out parameter to the callers TALLOC_CTX */
r->out.error_string = NULL;
r->out.join_password = r2->out.join_password;
diff --git a/source4/scripting/ejs/smbcalls_creds.c b/source4/scripting/ejs/smbcalls_creds.c
index cc2ccf8c47..3cd554b957 100644
--- a/source4/scripting/ejs/smbcalls_creds.c
+++ b/source4/scripting/ejs/smbcalls_creds.c
@@ -240,6 +240,16 @@ int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv)
return ejs_credentials_obj(obj, cmdline_credentials);
}
+static int ejs_credentials_update_all_keytabs(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+ if (!NT_STATUS_IS_OK(cli_credentials_update_all_keytabs(mprMemCtx()))) {
+ mpr_Return(eid, mprCreateBoolVar(False));
+ } else {
+ mpr_Return(eid, mprCreateBoolVar(True));
+ }
+ return 0;
+}
+
/*
setup C functions that be called from ejs
@@ -247,4 +257,6 @@ int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv)
void smb_setup_ejs_credentials(void)
{
ejsDefineCFunction(-1, "credentials_init", ejs_credentials_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+ ejsDefineCFunction(-1, "credentials_update_all_keytabs", ejs_credentials_update_all_keytabs, NULL, MPR_VAR_SCRIPT_HANDLE);
}
+
diff --git a/source4/scripting/libjs/provision.js b/source4/scripting/libjs/provision.js
index 513fb23cd9..0b6a31ae4f 100644
--- a/source4/scripting/libjs/provision.js
+++ b/source4/scripting/libjs/provision.js
@@ -302,6 +302,9 @@ function provision(subobj, message, blank, paths)
setup_file("provision.zone",
paths.dns,
subobj);
+ message("Setting up keytabs\n");
+ var keytab_ok = credentials_update_all_keytabs();
+ assert(keytab_ok);
}
/*
diff --git a/source4/setup/secrets.ldif b/source4/setup/secrets.ldif
index c573ad3b56..43c3f69c9d 100644
--- a/source4/setup/secrets.ldif
+++ b/source4/setup/secrets.ldif
@@ -26,6 +26,7 @@ cn: Primary Domains
dn: flatname=${DOMAIN},CN=Primary Domains
objectClass: top
objectClass: primaryDomain
+objectClass: kerberosSecret
flatname: ${DOMAIN}
realm: ${REALM}
secret: ${MACHINEPASS}
@@ -35,10 +36,12 @@ whenCreated: ${LDAPTIME}
whenChanged: ${LDAPTIME}
msDS-KeyVersionNumber: 1
objectSid: ${DOMAINSID}
+privateKeytab: secrets.keytab
dn: samAccountName=krbtgt,flatname=${DOMAIN},CN=Principals
objectClass: top
objectClass: secret
+objectClass: kerberosSecret
flatname: ${DOMAIN}
realm: ${REALM}
secret: ${KRBTGTPASS}
@@ -49,3 +52,4 @@ msDS-KeyVersionNumber: 1
objectSid: ${DOMAINSID}
servicePrincipalName: kadmin/changepw
saltPrincipal: krbtgt@${REALM}
+privateKeytab: secrets.keytab