diff options
Diffstat (limited to 'source4')
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 |