diff options
-rw-r--r-- | source4/auth/auth.h | 1 | ||||
-rw-r--r-- | source4/auth/auth_util.c | 2 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.c | 1 | ||||
-rw-r--r-- | source4/auth/credentials/credentials.h | 2 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 113 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 101 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos.h | 10 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/accept_sec_context.c | 38 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/acquire_cred.c | 132 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/copy_ccache.c | 90 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/delete_sec_context.c | 2 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/gssapi.h | 8 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/gssapi_locl.h | 12 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/init_sec_context.c | 46 | ||||
-rw-r--r-- | source4/heimdal/lib/gssapi/release_cred.c | 6 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/ticket.c | 6 | ||||
-rw-r--r-- | source4/ntvfs/cifs/vfs_cifs.c | 28 |
17 files changed, 427 insertions, 171 deletions
diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 9f2e0b6a07..58f72aa8af 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -118,6 +118,7 @@ struct auth_session_info { struct security_token *security_token; struct auth_serversupplied_info *server_info; DATA_BLOB session_key; + struct cli_credentials *credentials; }; struct auth_method_context; diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c index 753f680fb1..df4e510c2f 100644 --- a/source4/auth/auth_util.c +++ b/source4/auth/auth_util.c @@ -526,6 +526,8 @@ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, &session_info->security_token); NT_STATUS_NOT_OK_RETURN(nt_status); + session_info->credentials = NULL; + *_session_info = session_info; return NT_STATUS_OK; } diff --git a/source4/auth/credentials/credentials.c b/source4/auth/credentials/credentials.c index 5d2c5c553e..86a3df0077 100644 --- a/source4/auth/credentials/credentials.c +++ b/source4/auth/credentials/credentials.c @@ -46,6 +46,7 @@ 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->keytab_obtained = CRED_UNINITIALISED; cred->principal_obtained = CRED_UNINITIALISED; diff --git a/source4/auth/credentials/credentials.h b/source4/auth/credentials/credentials.h index b85337bd18..3e84db52a5 100644 --- a/source4/auth/credentials/credentials.h +++ b/source4/auth/credentials/credentials.h @@ -47,6 +47,7 @@ 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 principal_obtained; enum credentials_obtained keytab_obtained; @@ -62,6 +63,7 @@ struct cli_credentials { struct samr_Password *nt_hash; struct ccache_container *ccache; + struct gssapi_creds_container *gssapi_creds; struct keytab_container *keytab; const char *(*workstation_cb) (struct cli_credentials *); diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c index abb8418748..a3761e8359 100644 --- a/source4/auth/credentials/credentials_krb5.c +++ b/source4/auth/credentials/credentials_krb5.c @@ -85,7 +85,7 @@ int cli_credentials_set_from_ccache(struct cli_credentials *cred, return 0; } - +/* Free a memory ccache */ static int free_mccache(void *ptr) { struct ccache_container *ccc = ptr; krb5_cc_destroy(ccc->smb_krb5_context->krb5_context, ccc->ccache); @@ -93,6 +93,7 @@ static int free_mccache(void *ptr) { return 0; } +/* Free a disk-based ccache */ static int free_dccache(void *ptr) { struct ccache_container *ccc = ptr; krb5_cc_close(ccc->smb_krb5_context->krb5_context, ccc->ccache); @@ -163,7 +164,7 @@ int cli_credentials_set_ccache(struct cli_credentials *cred, } -int cli_credentials_new_ccache(struct cli_credentials *cred) +int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc) { krb5_error_code ret; char *rand_string; @@ -211,6 +212,10 @@ int cli_credentials_new_ccache(struct cli_credentials *cred) talloc_steal(cred, ccc); talloc_free(ccache_name); + if (_ccc) { + *_ccc = ccc; + } + return ret; } @@ -228,7 +233,7 @@ int cli_credentials_get_ccache(struct cli_credentials *cred, return EINVAL; } - ret = cli_credentials_new_ccache(cred); + ret = cli_credentials_new_ccache(cred, NULL); if (ret) { return ret; } @@ -245,6 +250,108 @@ int cli_credentials_get_ccache(struct cli_credentials *cred, return ret; } +static int free_gssapi_creds(void *ptr) { + OM_uint32 min_stat, maj_stat; + struct gssapi_creds_container *gcc = ptr; + maj_stat = gss_release_cred(&min_stat, + &gcc->creds); + return 0; +} + +int cli_credentials_get_client_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 ccache_container *ccache; + if (cred->gss_creds_obtained >= (MAX(cred->ccache_obtained, + MAX(cred->principal_obtained, + cred->username_obtained)))) { + *_gcc = cred->gssapi_creds; + return 0; + } + ret = cli_credentials_get_ccache(cred, + &ccache); + if (ret) { + DEBUG(1, ("Failed to get CCACHE for GSSAPI client: %s\n", error_message(ret))); + return ret; + } + + gcc = talloc(cred, struct gssapi_creds_container); + if (!gcc) { + return ENOMEM; + } + + maj_stat = gss_krb5_import_ccache(&min_stat, ccache->ccache, + &gcc->creds); + if (maj_stat) { + if (min_stat) { + ret = min_stat; + } else { + ret = EINVAL; + } + } + if (ret == 0) { + cred->gss_creds_obtained = cred->ccache_obtained; + talloc_set_destructor(gcc, free_gssapi_creds); + cred->gssapi_creds = gcc; + *_gcc = gcc; + } + return ret; +} + +/** + Set a gssapi cred_id_t into the credentails system. + + 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. + + On sucess, the caller must not free gssapi_cred, as it now belongs + to the credentials system. +*/ + + int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, + gss_cred_id_t gssapi_cred, + enum credentials_obtained obtained) +{ + int ret; + OM_uint32 maj_stat, min_stat; + struct ccache_container *ccc; + struct gssapi_creds_container *gcc = talloc(cred, struct gssapi_creds_container); + if (!gcc) { + return ENOMEM; + } + + ret = cli_credentials_new_ccache(cred, &ccc); + if (ret != 0) { + return ret; + } + + maj_stat = gss_krb5_copy_ccache(&min_stat, + gssapi_cred, ccc->ccache); + if (maj_stat) { + if (min_stat) { + ret = min_stat; + } else { + ret = EINVAL; + } + } + + if (ret == 0) { + ret = cli_credentials_set_from_ccache(cred, obtained); + } + if (ret == 0) { + gcc->creds = gssapi_cred; + talloc_set_destructor(gcc, free_gssapi_creds); + + cred->gss_creds_obtained = obtained; + cred->gssapi_creds = gcc; + } + return ret; +} + int cli_credentials_get_keytab(struct cli_credentials *cred, struct keytab_container **_ktc) { diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index d59d19c636..4608b62db5 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -44,8 +44,10 @@ struct gensec_gssapi_state { krb5_ccache ccache; const char *ccache_name; struct keytab_container *keytab; + struct gssapi_creds_container *client_cred; gss_cred_id_t cred; + gss_cred_id_t delegated_cred_handle; }; static char *gssapi_error_string(TALLOC_CTX *mem_ctx, @@ -83,6 +85,10 @@ static int gensec_gssapi_destory(void *ptr) 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); + } if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) { maj_stat = gss_delete_sec_context (&min_stat, @@ -118,13 +124,14 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) /* TODO: Fill in channel bindings */ gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; - gensec_gssapi_state->want_flags = GSS_C_MUTUAL_FLAG; + gensec_gssapi_state->want_flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG; gensec_gssapi_state->got_flags = 0; 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); @@ -205,7 +212,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi } maj_stat = gsskrb5_acquire_cred(&min_stat, - gensec_gssapi_state->keytab->keytab, NULL, + gensec_gssapi_state->keytab->keytab, gensec_gssapi_state->server_name, GSS_C_INDEFINITE, GSS_C_NULL_OID_SET, @@ -227,7 +234,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi { struct gensec_gssapi_state *gensec_gssapi_state; struct cli_credentials *creds = gensec_get_credentials(gensec_security); - struct ccache_container *ccache; krb5_error_code ret; NTSTATUS nt_status; gss_buffer_desc name_token; @@ -235,6 +241,7 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi OM_uint32 maj_stat, min_stat; const char *hostname = gensec_get_target_hostname(gensec_security); const char *principal; + struct gssapi_creds_container *gcc; if (!hostname) { DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); @@ -256,29 +263,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi gensec_gssapi_state = gensec_security->private_data; - ret = cli_credentials_get_ccache(creds, - &ccache); - if (ret) { - DEBUG(1, ("Failed to get CCACHE for gensec_gssapi: %s\n", error_message(ret))); - return NT_STATUS_UNSUCCESSFUL; - } - - principal = cli_credentials_get_principal(creds, - gensec_gssapi_state); - 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->client_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_INVALID_PARAMETER; - } - principal = gensec_get_target_principal(gensec_security); if (principal && lp_client_use_spnego_principal()) { name_token.value = discard_const_p(uint8_t, principal); @@ -307,28 +291,20 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi return NT_STATUS_INVALID_PARAMETER; } - maj_stat = gsskrb5_acquire_cred(&min_stat, - NULL, ccache->ccache, - gensec_gssapi_state->client_name, - GSS_C_INDEFINITE, - GSS_C_NULL_OID_SET, - GSS_C_INITIATE, - &gensec_gssapi_state->cred, - NULL, - NULL); - if (maj_stat) { - switch (min_stat) { - case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN: - DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n", - hostname, gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat))); - return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ - default: - DEBUG(1, ("Aquiring initiator credentails failed: %s\n", - gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat))); - return NT_STATUS_UNSUCCESSFUL; - } + ret = cli_credentials_get_client_gss_creds(creds, &gcc); + switch (ret) { + case 0: + break; + case KRB5_KDC_UNREACH: + DEBUG(3, ("Cannot reach a KDC we require\n")); + return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */ + default: + DEBUG(1, ("Aquiring initiator credentails failed\n")); + return NT_STATUS_UNSUCCESSFUL; } + gensec_gssapi_state->client_cred = gcc; + return NT_STATUS_OK; } @@ -369,7 +345,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, const DATA_BLOB in, DATA_BLOB *out) { struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; OM_uint32 maj_stat, min_stat; OM_uint32 min_stat2; gss_buffer_desc input_token, output_token; @@ -381,7 +357,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, case GENSEC_CLIENT: { maj_stat = gss_init_sec_context(&min_stat, - gensec_gssapi_state->cred, + gensec_gssapi_state->client_cred->creds, &gensec_gssapi_state->gssapi_context, gensec_gssapi_state->server_name, discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid), @@ -407,7 +383,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, &output_token, &gensec_gssapi_state->got_flags, NULL, - NULL); + &gensec_gssapi_state->delegated_cred_handle); gensec_gssapi_state->gss_oid = gss_oid_p; break; } @@ -420,6 +396,12 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length); gss_release_buffer(&min_stat2, &output_token); + if (gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG) { + DEBUG(5, ("gensec_gssapi: credentials were delegated\n")); + } else { + DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n")); + } + return NT_STATUS_OK; } else if (maj_stat == GSS_S_CONTINUE_NEEDED) { *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length); @@ -941,6 +923,27 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key); NT_STATUS_NOT_OK_RETURN(nt_status); + if (!(gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG)) { + DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client")); + } else { + krb5_error_code ret; + DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n")); + session_info->credentials = cli_credentials_init(session_info); + if (!session_info->credentials) { + return NT_STATUS_NO_MEMORY; + } + + cli_credentials_set_conf(session_info->credentials); + + ret = cli_credentials_set_client_gss_creds(session_info->credentials, + gensec_gssapi_state->delegated_cred_handle, + CRED_SPECIFIED); + if (ret) { + return NT_STATUS_NO_MEMORY; + } + /* It has been taken from this place... */ + gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL; + } *_session_info = session_info; return NT_STATUS_OK; diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h index 070293df68..9813290650 100644 --- a/source4/auth/kerberos/kerberos.h +++ b/source4/auth/kerberos/kerberos.h @@ -29,6 +29,11 @@ struct ccache_container { }; +struct gssapi_creds_container { + gss_cred_id_t creds; +}; + + struct keytab_container { struct smb_krb5_context *smb_krb5_context; krb5_keytab keytab; @@ -155,5 +160,10 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, krb5_principal client_principal, time_t tgs_authtime, DATA_BLOB *pac); + + int cli_credentials_set_client_gss_creds(struct cli_credentials *cred, + gss_cred_id_t gssapi_cred, + enum credentials_obtained obtained); + #endif /* HAVE_KRB5 */ diff --git a/source4/heimdal/lib/gssapi/accept_sec_context.c b/source4/heimdal/lib/gssapi/accept_sec_context.c index 8e354c3136..5d43cdcb43 100644 --- a/source4/heimdal/lib/gssapi/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/accept_sec_context.c @@ -239,7 +239,7 @@ gsskrb5_acceptor_ready( OM_uint32 ret; int32_t seq_number; int is_cfx = 0; - u_int32_t flags = (*context_handle)->flags; + u_int32_t *flags = &(*context_handle)->flags; krb5_auth_getremoteseqnumber (gssapi_krb5_context, (*context_handle)->auth_context, @@ -249,11 +249,11 @@ gsskrb5_acceptor_ready( ret = _gssapi_msg_order_create(minor_status, &(*context_handle)->order, - _gssapi_msg_order_f(flags), + _gssapi_msg_order_f(*flags), seq_number, 0, is_cfx); if (ret) return ret; - if (!(flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(flags)) { + if (!(*flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(*flags)) { krb5_auth_con_setlocalseqnumber(gssapi_krb5_context, (*context_handle)->auth_context, seq_number); @@ -262,11 +262,14 @@ gsskrb5_acceptor_ready( /* * We should handle the delegation ticket, in case it's there */ - if ((*context_handle)->fwd_data.length > 0 && (flags & GSS_C_DELEG_FLAG)) { + if ((*context_handle)->fwd_data.length > 0 && (*flags & GSS_C_DELEG_FLAG)) { ret = gsskrb5_accept_delegated_token(minor_status, context_handle, delegated_cred_handle); if (ret) return ret; + } else { + /* Well, looks like it wasn't there after all */ + *flags &= ~GSS_C_DELEG_FLAG; } (*context_handle)->state = ACCEPTOR_READY; @@ -297,10 +300,9 @@ gsskrb5_acceptor_start krb5_ticket *ticket = NULL; krb5_keytab keytab = NULL; krb5_keyblock *keyblock = NULL; - krb5_data fwd_data; int is_cfx = 0; - krb5_data_zero (&fwd_data); + krb5_data_zero (&(*context_handle)->fwd_data); /* * We may, or may not, have an escapsulation. @@ -415,7 +417,7 @@ gsskrb5_acceptor_start input_chan_bindings, authenticator->cksum, &flags, - &fwd_data); + &(*context_handle)->fwd_data); krb5_free_authenticator(gssapi_krb5_context, &authenticator); if (ret) { return ret; @@ -461,15 +463,9 @@ gsskrb5_acceptor_start } } - /* - * We need to send the flags back to the caller - */ flags |= GSS_C_TRANS_FLAG; - if (ret_flags) - *ret_flags = flags; - - /* And remember them for later */ + /* Remember the flags */ (*context_handle)->lifetime = ticket->ticket.endtime; (*context_handle)->flags = flags; @@ -491,11 +487,23 @@ gsskrb5_acceptor_start * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from the client */ if (flags & GSS_C_DCE_STYLE) { + if (ret_flags) { + /* Return flags to caller, but we haven't processed delgations yet */ + *ret_flags = flags & ~GSS_C_DELEG_FLAG; + } + (*context_handle)->state = ACCEPTOR_WAIT_FOR_DCESTYLE; return GSS_S_CONTINUE_NEEDED; } - return gsskrb5_acceptor_ready(minor_status, context_handle, delegated_cred_handle); + ret = gsskrb5_acceptor_ready(minor_status, context_handle, delegated_cred_handle); + + /* + * We need to send the flags back to the caller + */ + + *ret_flags = (*context_handle)->flags; + return ret; } static OM_uint32 diff --git a/source4/heimdal/lib/gssapi/acquire_cred.c b/source4/heimdal/lib/gssapi/acquire_cred.c index 23c2603352..d67b400920 100644 --- a/source4/heimdal/lib/gssapi/acquire_cred.c +++ b/source4/heimdal/lib/gssapi/acquire_cred.c @@ -33,7 +33,53 @@ #include "gssapi_locl.h" -RCSID("$Id: acquire_cred.c,v 1.23 2005/10/21 12:44:08 lha Exp $"); +RCSID("$Id: acquire_cred.c,v 1.24 2005/10/26 11:25:16 lha Exp $"); + +OM_uint32 +_gssapi_krb5_ccache_lifetime(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal principal, + OM_uint32 *lifetime) +{ + krb5_creds in_cred, *out_cred; + krb5_const_realm realm; + krb5_error_code kret; + + memset(&in_cred, 0, sizeof(in_cred)); + in_cred.client = principal; + + realm = krb5_principal_get_realm(gssapi_krb5_context, principal); + if (realm == NULL) { + gssapi_krb5_clear_status (); + *minor_status = KRB5_PRINC_NOMATCH; /* XXX */ + return GSS_S_FAILURE; + } + + kret = krb5_make_principal(gssapi_krb5_context, &in_cred.server, + realm, KRB5_TGS_NAME, realm, NULL); + if (kret) { + gssapi_krb5_set_error_string(); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_get_credentials(gssapi_krb5_context, 0, + id, &in_cred, &out_cred); + krb5_free_principal(gssapi_krb5_context, in_cred.server); + if (kret) { + gssapi_krb5_set_error_string(); + *minor_status = kret; + return GSS_S_FAILURE; + } + + *lifetime = out_cred->times.endtime; + krb5_free_creds(gssapi_krb5_context, out_cred); + + return GSS_S_COMPLETE; +} + + + static krb5_error_code get_keytab(krb5_context context, krb5_keytab *keytab) @@ -61,7 +107,6 @@ static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, krb5_context context, krb5_keytab keytab, - krb5_ccache ccache, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, @@ -75,10 +120,11 @@ static OM_uint32 acquire_initiator_cred krb5_creds cred; krb5_principal def_princ; krb5_get_init_creds_opt *opt; + krb5_ccache ccache; krb5_error_code kret; - krb5_boolean made_ccache = FALSE; krb5_boolean made_keytab = FALSE; + ccache = NULL; def_princ = NULL; ret = GSS_S_FAILURE; memset(&cred, 0, sizeof(cred)); @@ -86,29 +132,22 @@ static OM_uint32 acquire_initiator_cred /* If we have a preferred principal, lets try to find it in all * caches, otherwise, fall back to default cache. Ignore * errors. */ - if (ccache == NULL && handle->principal) { + if (handle->principal) kret = krb5_cc_cache_match (gssapi_krb5_context, handle->principal, NULL, &ccache); - if (kret) { - ccache = NULL; - } else { - made_ccache = TRUE; - } - } + if (ccache == NULL) { kret = krb5_cc_default(gssapi_krb5_context, &ccache); if (kret) goto end; - made_ccache = TRUE; } kret = krb5_cc_get_principal(context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ krb5_cc_destroy(context, ccache); - made_ccache = FALSE; ccache = NULL; kret = 0; } else if (handle->principal == NULL) { @@ -133,65 +172,41 @@ static OM_uint32 acquire_initiator_cred if (kret) goto end; } - if (keytab != NULL) { - kret = get_keytab(context, &keytab); - if (kret) - goto end; - made_keytab = TRUE; - } - kret = krb5_get_init_creds_opt_alloc(context, &opt); + kret = get_keytab(context, &keytab); + if (kret) + goto end; + kret = krb5_get_init_creds_opt_alloc(gssapi_krb5_context, &opt); if (kret) goto end; - kret = krb5_get_init_creds_keytab(context, &cred, + kret = krb5_get_init_creds_keytab(gssapi_krb5_context, &cred, handle->principal, keytab, 0, NULL, opt); krb5_get_init_creds_opt_free(opt); if (kret) goto end; - if (ccache == NULL) { - kret = krb5_cc_gen_new(context, &krb5_mcc_ops, - &ccache); - if (kret) - goto end; - made_ccache = TRUE; - } - kret = krb5_cc_initialize(context, ccache, cred.client); + kret = krb5_cc_gen_new(gssapi_krb5_context, &krb5_mcc_ops, + &ccache); if (kret) goto end; - kret = krb5_cc_store_cred(context, ccache, &cred); + kret = krb5_cc_initialize(gssapi_krb5_context, ccache, cred.client); if (kret) goto end; - handle->lifetime = cred.times.endtime; - } else { - krb5_creds in_cred, *out_cred; - krb5_const_realm realm; - - memset(&in_cred, 0, sizeof(in_cred)); - in_cred.client = handle->principal; - - realm = krb5_principal_get_realm(context, - handle->principal); - if (realm == NULL) { - kret = KRB5_PRINC_NOMATCH; /* XXX */ - goto end; - } - - kret = krb5_make_principal(context, &in_cred.server, - realm, KRB5_TGS_NAME, realm, NULL); + kret = krb5_cc_store_cred(gssapi_krb5_context, ccache, &cred); if (kret) goto end; + handle->lifetime = cred.times.endtime; + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + } else { - kret = krb5_get_credentials(context, 0, - ccache, &in_cred, &out_cred); - krb5_free_principal(context, in_cred.server); - if (kret) + ret = _gssapi_krb5_ccache_lifetime(minor_status, + ccache, + handle->principal, + &handle->lifetime); + if (ret != GSS_S_COMPLETE) goto end; - - handle->lifetime = out_cred->times.endtime; - krb5_free_creds(context, out_cred); + kret = 0; } handle->ccache = ccache; - handle->made_ccache = made_ccache; ret = GSS_S_COMPLETE; end: @@ -202,8 +217,8 @@ end: if (made_keytab) krb5_kt_close(context, keytab); if (ret != GSS_S_COMPLETE) { - if (made_ccache) - krb5_cc_close(context, ccache); + if (ccache != NULL) + krb5_cc_close(gssapi_krb5_context, ccache); if (kret != 0) { *minor_status = kret; gssapi_krb5_set_error_string (); @@ -255,7 +270,6 @@ end: OM_uint32 gsskrb5_acquire_cred (OM_uint32 * minor_status, struct krb5_keytab_data *keytab, - struct krb5_ccache_data *ccache, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, @@ -314,7 +328,7 @@ 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, ccache, + keytab, desired_name, time_req, desired_mechs, cred_usage, handle, actual_mechs, time_rec); @@ -379,7 +393,7 @@ OM_uint32 gss_acquire_cred ) { return gsskrb5_acquire_cred(minor_status, - NULL, NULL, + NULL, desired_name, time_req, desired_mechs, diff --git a/source4/heimdal/lib/gssapi/copy_ccache.c b/source4/heimdal/lib/gssapi/copy_ccache.c index 828ca64156..0f2f155870 100644 --- a/source4/heimdal/lib/gssapi/copy_ccache.c +++ b/source4/heimdal/lib/gssapi/copy_ccache.c @@ -33,7 +33,7 @@ #include "gssapi_locl.h" -RCSID("$Id: copy_ccache.c,v 1.7 2003/09/01 15:11:09 lha Exp $"); +RCSID("$Id: copy_ccache.c,v 1.9 2005/10/31 16:02:08 lha Exp $"); OM_uint32 gss_krb5_copy_ccache(OM_uint32 *minor_status, @@ -61,6 +61,94 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status, return GSS_S_COMPLETE; } + +OM_uint32 +gss_krb5_import_ccache(OM_uint32 *minor_status, + krb5_ccache in, + gss_cred_id_t *cred) +{ + krb5_error_code kret; + gss_cred_id_t handle; + OM_uint32 ret; + + *cred = NULL; + + GSSAPI_KRB5_INIT (); + + handle = (gss_cred_id_t)calloc(1, sizeof(*handle)); + if (handle == GSS_C_NO_CREDENTIAL) { + gssapi_krb5_clear_status (); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + handle->usage = GSS_C_INITIATE; + + 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; + } + + 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; + } + + 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; + } + + { + const char *type, *name; + 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; + } + + kret = krb5_cc_resolve(gssapi_krb5_context, str, &handle->ccache); + free(str); + if (kret) + goto out; + } + + *minor_status = 0; + *cred = handle; + return GSS_S_COMPLETE; + +out: + gssapi_krb5_set_error_string (); + if (handle->principal) + krb5_free_principal(gssapi_krb5_context, handle->principal); + HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + free(handle); + *minor_status = kret; + return GSS_S_FAILURE; +} + + OM_uint32 gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, gss_ctx_id_t context_handle, diff --git a/source4/heimdal/lib/gssapi/delete_sec_context.c b/source4/heimdal/lib/gssapi/delete_sec_context.c index 83658fa76c..301197aa4c 100644 --- a/source4/heimdal/lib/gssapi/delete_sec_context.c +++ b/source4/heimdal/lib/gssapi/delete_sec_context.c @@ -66,6 +66,8 @@ OM_uint32 gss_delete_sec_context (*context_handle)->service_keyblock); if((*context_handle)->order) _gssapi_msg_order_destroy(&(*context_handle)->order); + if ((*context_handle)->fwd_data.length > 0) + free((*context_handle)->fwd_data.data); HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex); HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex); diff --git a/source4/heimdal/lib/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi.h index 4bf6780daa..64a31d1eee 100644 --- a/source4/heimdal/lib/gssapi/gssapi.h +++ b/source4/heimdal/lib/gssapi/gssapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: gssapi.h,v 1.37 2005/02/21 08:48:15 lukeh Exp $ */ +/* $Id: gssapi.h,v 1.38 2005/10/26 11:22:13 lha Exp $ */ #ifndef GSSAPI_H_ #define GSSAPI_H_ @@ -778,7 +778,6 @@ OM_uint32 gss_unseal OM_uint32 gsskrb5_acquire_cred (OM_uint32 * minor_status, struct krb5_keytab_data *keytab, - struct krb5_ccache_data *ccache, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, @@ -806,6 +805,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_get_tkt_flags (OM_uint32 */*minor*/, gss_ctx_id_t /*context_handle*/, diff --git a/source4/heimdal/lib/gssapi/gssapi_locl.h b/source4/heimdal/lib/gssapi/gssapi_locl.h index 1d22099877..aa663e87a6 100644 --- a/source4/heimdal/lib/gssapi/gssapi_locl.h +++ b/source4/heimdal/lib/gssapi/gssapi_locl.h @@ -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. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: gssapi_locl.h,v 1.41 2005/10/12 15:20:37 lha Exp $ */ +/* $Id: gssapi_locl.h,v 1.42 2005/10/26 11:23:48 lha Exp $ */ #ifndef GSSAPI_LOCL_H #define GSSAPI_LOCL_H @@ -79,12 +79,13 @@ typedef struct gss_ctx_id_t_desc_struct { typedef struct gss_cred_id_t_desc_struct { gss_name_t principal; + int cred_flags; +#define GSS_CF_DESTROY_CRED_ON_RELEASE 1 krb5_boolean made_keytab; struct krb5_keytab_data *keytab; OM_uint32 lifetime; gss_cred_usage_t usage; gss_OID_set mechanisms; - krb5_boolean made_ccache; struct krb5_ccache_data *ccache; HEIMDAL_MUTEX cred_id_mutex; } gss_cred_id_t_desc; @@ -108,7 +109,6 @@ struct gssapi_thr_context { */ krb5_error_code gssapi_krb5_init (void); -krb5_error_code gssapi_krb5_init_ev (void *event_context); #define GSSAPI_KRB5_INIT() do { \ krb5_error_code kret_gss_init; \ @@ -271,6 +271,10 @@ _gss_check_compat(OM_uint32 *, gss_name_t, const char *, OM_uint32 gssapi_lifetime_left(OM_uint32 *, OM_uint32, OM_uint32 *); +OM_uint32 +_gssapi_krb5_ccache_lifetime(OM_uint32 *, krb5_ccache, + krb5_principal, OM_uint32 *); + /* sequence */ OM_uint32 diff --git a/source4/heimdal/lib/gssapi/init_sec_context.c b/source4/heimdal/lib/gssapi/init_sec_context.c index 93e8d44c86..b8eb748bf5 100644 --- a/source4/heimdal/lib/gssapi/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/init_sec_context.c @@ -162,7 +162,7 @@ _gsskrb5_create_ctx( static OM_uint32 gsskrb5_get_creds( OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, + krb5_ccache ccache, gss_ctx_id_t * context_handle, const gss_name_t target_name, OM_uint32 time_req, @@ -172,22 +172,10 @@ gsskrb5_get_creds( OM_uint32 ret; krb5_error_code kret; krb5_creds this_cred; - krb5_ccache ccache = NULL; OM_uint32 lifetime_rec; *cred = NULL; - if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) { - kret = krb5_cc_default (gssapi_krb5_context, &ccache); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } else { - ccache = initiator_cred_handle->ccache; - } - kret = krb5_cc_get_principal(gssapi_krb5_context, ccache, &(*context_handle)->source); @@ -246,10 +234,6 @@ gsskrb5_get_creds( if (time_rec) *time_rec = lifetime_rec; - if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) { - krb5_cc_close(gssapi_krb5_context, ccache); - } - return GSS_S_COMPLETE; } @@ -351,7 +335,7 @@ do_delegation (krb5_auth_context ac, static OM_uint32 gsskrb5_initiator_start (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, + krb5_ccache ccache, gss_ctx_id_t * context_handle, const gss_name_t target_name, const gss_OID mech_type, @@ -369,7 +353,6 @@ gsskrb5_initiator_start krb5_flags ap_options; krb5_creds *cred = NULL; krb5_data outbuf; - krb5_ccache ccache = NULL; u_int32_t flags; krb5_data authenticator; Checksum cksum; @@ -383,7 +366,7 @@ gsskrb5_initiator_start /* We need to get the credentials for the requested target */ ret = gsskrb5_get_creds(minor_status, - initiator_cred_handle, + ccache, context_handle, target_name, time_req, @@ -543,7 +526,7 @@ gsskrb5_initiator_start static OM_uint32 gsskrb5_initiator_wait_for_mutual( OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, + krb5_ccache ccache, gss_ctx_id_t * context_handle, const gss_name_t target_name, const gss_OID mech_type, @@ -697,6 +680,8 @@ gsskrb5_init_sec_context ) { OM_uint32 ret; + krb5_error_code kret; + krb5_ccache ccache = NULL; if (*context_handle == GSS_C_NO_CONTEXT) { ret = _gsskrb5_create_ctx(minor_status, @@ -708,12 +693,23 @@ gsskrb5_init_sec_context if (actual_mech_type) *actual_mech_type = GSS_KRB5_MECHANISM; + if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) { + kret = krb5_cc_default (gssapi_krb5_context, &ccache); + if (kret) { + gssapi_krb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + } else { + ccache = initiator_cred_handle->ccache; + } + HEIMDAL_MUTEX_lock(&(*context_handle)->ctx_id_mutex); switch ((*context_handle)->state) { case INITIATOR_START: ret = gsskrb5_initiator_start(minor_status, - initiator_cred_handle, + ccache, context_handle, target_name, mech_type, @@ -727,7 +723,7 @@ gsskrb5_init_sec_context break; case INITIATOR_WAIT_FOR_MUTAL: ret = gsskrb5_initiator_wait_for_mutual(minor_status, - initiator_cred_handle, + ccache, context_handle, target_name, mech_type, @@ -771,6 +767,10 @@ gsskrb5_init_sec_context break; } + if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) { + krb5_cc_close(gssapi_krb5_context, ccache); + } + HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex); return ret; diff --git a/source4/heimdal/lib/gssapi/release_cred.c b/source4/heimdal/lib/gssapi/release_cred.c index 8ae65dd528..ddd80c144b 100644 --- a/source4/heimdal/lib/gssapi/release_cred.c +++ b/source4/heimdal/lib/gssapi/release_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -54,10 +54,10 @@ OM_uint32 gss_release_cred krb5_free_principal(gssapi_krb5_context, (*cred_handle)->principal); if ((*cred_handle)->made_keytab) krb5_kt_close(gssapi_krb5_context, (*cred_handle)->keytab); - if ((*cred_handle)->made_ccache) { + if ((*cred_handle)->ccache != NULL) { const krb5_cc_ops *ops; ops = krb5_cc_get_ops(gssapi_krb5_context, (*cred_handle)->ccache); - if (ops == &krb5_mcc_ops) + if ((*cred_handle)->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) krb5_cc_destroy(gssapi_krb5_context, (*cred_handle)->ccache); else krb5_cc_close(gssapi_krb5_context, (*cred_handle)->ccache); diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 8f4f8fb152..7dae26acf2 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c,v 1.12 2004/05/25 21:44:47 lha Exp $"); +RCSID("$Id: ticket.c,v 1.14 2005/10/27 13:21:42 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, @@ -151,6 +151,7 @@ find_type_in_ad(krb5_context context, goto out; break; } +#if 0 /* XXX test */ case KRB5_AUTHDATA_KDC_ISSUED: { AD_KDCIssued child; @@ -199,6 +200,7 @@ find_type_in_ad(krb5_context context, goto out; break; } +#endif case KRB5_AUTHDATA_AND_OR: if (!failp) break; @@ -229,7 +231,7 @@ out: /* * Extract the authorization data type of `type' from the * 'ticket'. Store the field in `data'. This function is to use for - * kerberos applications + * kerberos applications. */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index cb6fbb3880..5d0576e8f9 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -32,6 +32,7 @@ #include "libcli/smb_composite/smb_composite.h" #include "smb_server/smb_server.h" #include "smbd/service_stream.h" +#include "auth/auth.h" /* this is stored in ntvfs_private */ struct cvfs_private { @@ -106,11 +107,6 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, remote_share = sharename; } - if (!host || !user || !pass || !domain) { - DEBUG(1,("CIFS backend: You must supply server, user, password and domain\n")); - return NT_STATUS_INVALID_PARAMETER; - } - private = talloc(req->tcon, struct cvfs_private); if (!private) { return NT_STATUS_NO_MEMORY; @@ -119,11 +115,23 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, ntvfs->private_data = private; - credentials = cli_credentials_init(private); - cli_credentials_set_username(credentials, user, CRED_SPECIFIED); - cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); - cli_credentials_set_password(credentials, pass, CRED_SPECIFIED); - cli_credentials_set_workstation(credentials, "vfs_cifs", CRED_SPECIFIED); + if (!host) { + DEBUG(1,("CIFS backend: You must supply server\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (user && pass && domain) { + credentials = cli_credentials_init(private); + cli_credentials_set_username(credentials, user, CRED_SPECIFIED); + cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED); + cli_credentials_set_password(credentials, pass, CRED_SPECIFIED); + cli_credentials_set_workstation(credentials, "vfs_cifs", CRED_SPECIFIED); + } else if (req->session->session_info->credentials) { + credentials = req->session->session_info->credentials; + } else { + DEBUG(1,("CIFS backend: You must supply server, user, password and domain or have delegated credentials\n")); + return NT_STATUS_INVALID_PARAMETER; + } /* connect to the server, using the smbd event context */ io.in.dest_host = host; |