OM_uint32 gss_import_sec_context ( OM_uint32 * minor_status, const gss_buffer_t interprocess_token, gss_ctx_id_t * context_handle ) { OM_uint32 ret = GSS_S_FAILURE; krb5_error_code kret; krb5_storage *sp; krb5_auth_context ac; krb5_address local, remote; krb5_address *localp, *remotep; krb5_data data; gss_buffer_desc buffer; krb5_keyblock keyblock; int32_t tmp; int32_t flags; OM_uint32 minor; int is_cfx = 0; GSSAPI_KRB5_INIT (); localp = remotep = NULL; sp = krb5_storage_from_mem (interprocess_token->value, interprocess_token->length); if (sp == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } *context_handle = malloc(sizeof(**context_handle)); if (*context_handle == NULL) { *minor_status = ENOMEM; krb5_storage_free (sp); return GSS_S_FAILURE; } memset (*context_handle, 0, sizeof(**context_handle)); HEIMDAL_MUTEX_init(&(*context_handle)->ctx_id_mutex); kret = krb5_auth_con_init (gssapi_krb5_context, &(*context_handle)->auth_context); if (kret) { gssapi_krb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } /* flags */ *minor_status = 0; if (krb5_ret_int32 (sp, &flags) != 0) goto failure; /* retrieve the auth context */ ac = (*context_handle)->auth_context; krb5_ret_int32 (sp, &ac->flags); if (flags & SC_LOCAL_ADDRESS) { if (krb5_ret_address (sp, localp = &local) != 0) goto failure; } if (flags & SC_REMOTE_ADDRESS) { if (krb5_ret_address (sp, remotep = &remote) != 0) goto failure; } krb5_auth_con_setaddrs (gssapi_krb5_context, ac, localp, remotep); if (localp) krb5_free_address (gssapi_krb5_context, localp); if (remotep) krb5_free_address (gssapi_krb5_context, remotep); localp = remotep = NULL; if (krb5_ret_int16 (sp, &ac->local_port) != 0) goto failure; if (krb5_ret_int16 (sp, &ac->remote_port) != 0) goto failure; if (flags & SC_KEYBLOCK) { if (krb5_ret_keyblock (sp, &keyblock) != 0) goto failure; krb5_auth_con_setkey (gssapi_krb5_context, ac, &keyblock); krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock); } if (flags & SC_LOCAL_SUBKEY) { if (krb5_ret_keyblock (sp, &keyblock) != 0) goto failure; krb5_auth_con_setlocalsubkey (gssapi_krb5_context, ac, &keyblock); krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock); } if (flags & SC_REMOTE_SUBKEY) { if (krb5_ret_keyblock (sp, &keyblock) != 0) goto failure; krb5_auth_con_setremotesubkey (gssapi_krb5_context, ac, &keyblock); krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock); } if (krb5_ret_int32 (sp, &ac->local_seqnumber)) goto failure; if (krb5_ret_int32 (sp, &ac->remote_seqnumber)) goto failure; if (krb5_ret_int32 (sp, &tmp) != 0) goto failure; ac->keytype = tmp; if (krb5_ret_int32 (sp, &tmp) != 0) goto failure; ac->cksumtype = tmp; /* names */ if (krb5_ret_data (sp, &data)) goto failure; buffer.value = data.data; buffer.length = data.length; ret = gss_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, &(*context_handle)->source); if (ret) { ret = gss_import_name (minor_status, &buffer, GSS_C_NO_OID, &(*context_handle)->source); if (ret) { krb5_data_free (&data); goto failure; } } krb5_data_free (&data); if (krb5_ret_data (sp, &data) != 0) goto failure; buffer.value = data.data; buffer.length = data.length; ret = gss_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, &(*context_handle)->target); if (ret) { ret = gss_import_name (minor_status, &buffer, GSS_C_NO_OID, &(*context_handle)->target); if (ret) { krb5_data_free (&data); goto failure; } } krb5_data_free (&data); if (krb5_ret_int32 (sp, &tmp)) goto failure; (*context_handle)->flags = tmp; if (krb5_ret_int32 (sp, &tmp)) goto failure; (*context_handle)->more_flags = tmp; if (krb5_ret_int32 (sp, &tmp) == 0) (*context_handle)->lifetime = tmp; else (*context_handle)->lifetime = GSS_C_INDEFINITE; gsskrb5_is_cfx(*context_handle, &is_cfx); ret = _gssapi_msg_order_create(minor_status, &(*context_handle)->order, _gssapi_msg_order_f((*context_handle)->flags), 0, 0, is_cfx); if (ret) goto failure; krb5_storage_free (sp); return GSS_S_COMPLETE; failure: krb5_auth_con_free (gssapi_krb5_context, (*context_handle)->auth_context); if ((*context_handle)->source != NULL) gss_release_name(&minor, &(*context_handle)->source); if ((*context_handle)->target != NULL) gss_release_name(&minor, &(*context_handle)->target); if (localp) krb5_free_address (gssapi_krb5_context, localp); if (remotep) krb5_free_address (gssapi_krb5_context, remotep); if((*context_handle)->order) _gssapi_msg_order_destroy(&(*context_handle)->order); HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex); krb5_storage_free (sp); free (*context_handle); *context_handle = GSS_C_NO_CONTEXT; return ret; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_sec_context ( OM_uint32 * minor_status, const gss_buffer_t interprocess_token, gss_ctx_id_t * context_handle ) { OM_uint32 ret = GSS_S_FAILURE; krb5_context context; krb5_error_code kret; krb5_storage *sp; krb5_auth_context ac; krb5_address local, remote; krb5_address *localp, *remotep; krb5_data data; gss_buffer_desc buffer; krb5_keyblock keyblock; int32_t flags, tmp; gsskrb5_ctx ctx; gss_name_t name; GSSAPI_KRB5_INIT (&context); *context_handle = GSS_C_NO_CONTEXT; localp = remotep = NULL; sp = krb5_storage_from_mem (interprocess_token->value, interprocess_token->length); if (sp == NULL) { *minor_status = ENOMEM; return GSS_S_FAILURE; } ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { *minor_status = ENOMEM; krb5_storage_free (sp); return GSS_S_FAILURE; } HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); kret = krb5_auth_con_init (context, &ctx->auth_context); if (kret) { *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } /* flags */ *minor_status = 0; if (krb5_ret_int32 (sp, &flags) != 0) goto failure; /* retrieve the auth context */ ac = ctx->auth_context; if (krb5_ret_int32 (sp, &tmp) != 0) goto failure; ac->flags = tmp; if (flags & SC_LOCAL_ADDRESS) { if (krb5_ret_address (sp, localp = &local) != 0) goto failure; } if (flags & SC_REMOTE_ADDRESS) { if (krb5_ret_address (sp, remotep = &remote) != 0) goto failure; } krb5_auth_con_setaddrs (context, ac, localp, remotep); if (localp) krb5_free_address (context, localp); if (remotep) krb5_free_address (context, remotep); localp = remotep = NULL; if (krb5_ret_int16 (sp, &ac->local_port) != 0) goto failure; if (krb5_ret_int16 (sp, &ac->remote_port) != 0) goto failure; if (flags & SC_KEYBLOCK) { if (krb5_ret_keyblock (sp, &keyblock) != 0) goto failure; krb5_auth_con_setkey (context, ac, &keyblock); krb5_free_keyblock_contents (context, &keyblock); } if (flags & SC_LOCAL_SUBKEY) { if (krb5_ret_keyblock (sp, &keyblock) != 0) goto failure; krb5_auth_con_setlocalsubkey (context, ac, &keyblock); krb5_free_keyblock_contents (context, &keyblock); } if (flags & SC_REMOTE_SUBKEY) { if (krb5_ret_keyblock (sp, &keyblock) != 0) goto failure; krb5_auth_con_setremotesubkey (context, ac, &keyblock); krb5_free_keyblock_contents (context, &keyblock); } if (krb5_ret_uint32 (sp, &ac->local_seqnumber)) goto failure; if (krb5_ret_uint32 (sp, &ac->remote_seqnumber)) goto failure; if (krb5_ret_int32 (sp, &tmp) != 0) goto failure; ac->keytype = tmp; if (krb5_ret_int32 (sp, &tmp) != 0) goto failure; ac->cksumtype = tmp; /* names */ if (krb5_ret_data (sp, &data)) goto failure; buffer.value = data.data; buffer.length = data.length; ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, &name); if (ret) { ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, &name); if (ret) { krb5_data_free (&data); goto failure; } } ctx->source = (krb5_principal)name; krb5_data_free (&data); if (krb5_ret_data (sp, &data) != 0) goto failure; buffer.value = data.data; buffer.length = data.length; ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, &name); if (ret) { ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, &name); if (ret) { krb5_data_free (&data); goto failure; } } ctx->target = (krb5_principal)name; krb5_data_free (&data); if (krb5_ret_int32 (sp, &tmp)) goto failure; ctx->flags = tmp; if (krb5_ret_int32 (sp, &tmp)) goto failure; ctx->more_flags = tmp; if (krb5_ret_int32 (sp, &tmp)) goto failure; ctx->endtime = tmp; ret = _gssapi_msg_order_import(minor_status, sp, &ctx->gk5c.order); if (ret) goto failure; krb5_storage_free (sp); _gsskrb5i_is_cfx(context, ctx, (ctx->more_flags & LOCAL) == 0); *context_handle = (gss_ctx_id_t)ctx; return GSS_S_COMPLETE; failure: krb5_auth_con_free (context, ctx->auth_context); if (ctx->source != NULL) krb5_free_principal(context, ctx->source); if (ctx->target != NULL) krb5_free_principal(context, ctx->target); if (localp) krb5_free_address (context, localp); if (remotep) krb5_free_address (context, remotep); if(ctx->gk5c.order) _gssapi_msg_order_destroy(&ctx->gk5c.order); HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); krb5_storage_free (sp); free (ctx); *context_handle = GSS_C_NO_CONTEXT; return ret; }
static OM_uint32 init_auth (OM_uint32 * minor_status, gsskrb5_cred initiator_cred_handle, gsskrb5_ctx ctx, krb5_const_principal name, const gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, const gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec ) { OM_uint32 ret = GSS_S_FAILURE; krb5_error_code kret; krb5_flags ap_options; krb5_creds *cred = NULL; krb5_data outbuf; krb5_ccache ccache = NULL; uint32_t flags; krb5_data authenticator; Checksum cksum; krb5_enctype enctype; krb5_data fwd_data; OM_uint32 lifetime_rec; krb5_data_zero(&outbuf); krb5_data_zero(&fwd_data); *minor_status = 0; if (actual_mech_type) *actual_mech_type = GSS_KRB5_MECHANISM; if (initiator_cred_handle == NULL) { kret = krb5_cc_default (_gsskrb5_context, &ccache); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } } else ccache = initiator_cred_handle->ccache; kret = krb5_cc_get_principal (_gsskrb5_context, ccache, &ctx->source); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } kret = krb5_copy_principal (_gsskrb5_context, name, &ctx->target); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } ret = _gss_DES3_get_mic_compat(minor_status, ctx); if (ret) goto failure; ret = gsskrb5_get_creds(minor_status, ccache, ctx, ctx->target, time_req, time_rec, &cred); if (ret) goto failure; ctx->lifetime = cred->times.endtime; ret = _gsskrb5_lifetime_left(minor_status, ctx->lifetime, &lifetime_rec); if (ret) { goto failure; } if (lifetime_rec == 0) { *minor_status = 0; ret = GSS_S_CONTEXT_EXPIRED; goto failure; } krb5_auth_con_setkey(_gsskrb5_context, ctx->auth_context, &cred->session); kret = krb5_auth_con_generatelocalsubkey(_gsskrb5_context, ctx->auth_context, &cred->session); if(kret) { _gsskrb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } /* * If the credential doesn't have ok-as-delegate, check what local * policy say about ok-as-delegate, default is FALSE that makes * code ignore the KDC setting and follow what the application * requested. If its TRUE, strip of the GSS_C_DELEG_FLAG if the * KDC doesn't set ok-as-delegate. */ if (!cred->flags.b.ok_as_delegate) { krb5_boolean delegate; krb5_appdefault_boolean(_gsskrb5_context, "gssapi", name->realm, "ok-as-delegate", FALSE, &delegate); if (delegate) req_flags &= ~GSS_C_DELEG_FLAG; } flags = 0; ap_options = 0; if (req_flags & GSS_C_DELEG_FLAG) do_delegation (ctx->auth_context, ccache, cred, name, &fwd_data, &flags); if (req_flags & GSS_C_MUTUAL_FLAG) { flags |= GSS_C_MUTUAL_FLAG; ap_options |= AP_OPTS_MUTUAL_REQUIRED; } if (req_flags & GSS_C_REPLAY_FLAG) flags |= GSS_C_REPLAY_FLAG; if (req_flags & GSS_C_SEQUENCE_FLAG) flags |= GSS_C_SEQUENCE_FLAG; if (req_flags & GSS_C_ANON_FLAG) ; /* XXX */ if (req_flags & GSS_C_DCE_STYLE) { /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */ flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG; ap_options |= AP_OPTS_MUTUAL_REQUIRED; } if (req_flags & GSS_C_IDENTIFY_FLAG) flags |= GSS_C_IDENTIFY_FLAG; if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) flags |= GSS_C_EXTENDED_ERROR_FLAG; flags |= GSS_C_CONF_FLAG; flags |= GSS_C_INTEG_FLAG; flags |= GSS_C_TRANS_FLAG; if (ret_flags) *ret_flags = flags; ctx->flags = flags; ctx->more_flags |= LOCAL; ret = _gsskrb5_create_8003_checksum (minor_status, input_chan_bindings, flags, &fwd_data, &cksum); krb5_data_free (&fwd_data); if (ret) goto failure; enctype = ctx->auth_context->keyblock->keytype; kret = krb5_build_authenticator (_gsskrb5_context, ctx->auth_context, enctype, cred, &cksum, NULL, &authenticator, KRB5_KU_AP_REQ_AUTH); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } kret = krb5_build_ap_req (_gsskrb5_context, enctype, cred, ap_options, authenticator, &outbuf); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; ret = GSS_S_FAILURE; goto failure; } ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token, (u_char *)"\x01\x00", GSS_KRB5_MECHANISM); if (ret) goto failure; krb5_data_free (&outbuf); krb5_free_creds(_gsskrb5_context, cred); free_Checksum(&cksum); if (initiator_cred_handle == NULL) krb5_cc_close(_gsskrb5_context, ccache); if (flags & GSS_C_MUTUAL_FLAG) { ctx->state = INITIATOR_WAIT_FOR_MUTAL; return GSS_S_CONTINUE_NEEDED; } return gsskrb5_initiator_ready(minor_status, ctx); failure: if(cred) krb5_free_creds(_gsskrb5_context, cred); if (ccache && initiator_cred_handle == NULL) krb5_cc_close(_gsskrb5_context, ccache); return ret; }
krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock) { return krb5_auth_con_setkey(context, auth_context, keyblock); }