accept_sec_context.c

来自「samba最新软件」· C语言 代码 · 共 802 行 · 第 1/2 页

C
802
字号
/* * Copyright (c) 1997 - 2006 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden).  * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * * 3. Neither the name of the Institute nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  */#include "krb5/gsskrb5_locl.h"RCSID("$Id: accept_sec_context.c 20199 2007-02-07 22:36:39Z lha $");HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;krb5_keytab _gsskrb5_keytab;OM_uint32_gsskrb5_register_acceptor_identity (const char *identity){    krb5_context context;    krb5_error_code ret;    ret = _gsskrb5_init(&context);    if(ret)	return GSS_S_FAILURE;        HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);    if(_gsskrb5_keytab != NULL) {	krb5_kt_close(context, _gsskrb5_keytab);	_gsskrb5_keytab = NULL;    }    if (identity == NULL) {	ret = krb5_kt_default(context, &_gsskrb5_keytab);    } else {	char *p;	asprintf(&p, "FILE:%s", identity);	if(p == NULL) {	    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);	    return GSS_S_FAILURE;	}	ret = krb5_kt_resolve(context, p, &_gsskrb5_keytab);	free(p);    }    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);    if(ret)	return GSS_S_FAILURE;    return GSS_S_COMPLETE;}void_gsskrb5i_is_cfx(gsskrb5_ctx ctx, int *is_cfx){    krb5_keyblock *key;    int acceptor = (ctx->more_flags & LOCAL) == 0;    *is_cfx = 0;    if (acceptor) {	if (ctx->auth_context->local_subkey)	    key = ctx->auth_context->local_subkey;	else	    key = ctx->auth_context->remote_subkey;    } else {	if (ctx->auth_context->remote_subkey)	    key = ctx->auth_context->remote_subkey;	else	    key = ctx->auth_context->local_subkey;    }    if (key == NULL)	key = ctx->auth_context->keyblock;    if (key == NULL)	return;	        switch (key->keytype) {    case ETYPE_DES_CBC_CRC:    case ETYPE_DES_CBC_MD4:    case ETYPE_DES_CBC_MD5:    case ETYPE_DES3_CBC_MD5:    case ETYPE_DES3_CBC_SHA1:    case ETYPE_ARCFOUR_HMAC_MD5:    case ETYPE_ARCFOUR_HMAC_MD5_56:	break;    default :	*is_cfx = 1;	if ((acceptor && ctx->auth_context->local_subkey) ||	    (!acceptor && ctx->auth_context->remote_subkey))	    ctx->more_flags |= ACCEPTOR_SUBKEY;	break;    }}static OM_uint32gsskrb5_accept_delegated_token(OM_uint32 * minor_status, gsskrb5_ctx ctx, krb5_context context, gss_cred_id_t * delegated_cred_handle    ){    krb5_ccache ccache = NULL;    krb5_error_code kret;    int32_t ac_flags, ret = GSS_S_COMPLETE;          *minor_status = 0;    /* XXX Create a new delegated_cred_handle? */    if (delegated_cred_handle == NULL) {	kret = krb5_cc_default (context, &ccache);    } else {	*delegated_cred_handle = NULL;	kret = krb5_cc_gen_new (context, &krb5_mcc_ops, &ccache);    }    if (kret) {	ctx->flags &= ~GSS_C_DELEG_FLAG;	goto out;    }    kret = krb5_cc_initialize(context, ccache, ctx->source);    if (kret) {	ctx->flags &= ~GSS_C_DELEG_FLAG;	goto out;    }          krb5_auth_con_removeflags(context,			      ctx->auth_context,			      KRB5_AUTH_CONTEXT_DO_TIME,			      &ac_flags);    kret = krb5_rd_cred2(context,			 ctx->auth_context,			 ccache,			 &ctx->fwd_data);    krb5_auth_con_setflags(context,			   ctx->auth_context,			   ac_flags);    if (kret) {	ctx->flags &= ~GSS_C_DELEG_FLAG;	ret = GSS_S_FAILURE;	*minor_status = kret;	goto out;    }    if (delegated_cred_handle) {	gsskrb5_cred handle;	ret = _gsskrb5_import_cred(minor_status,				   ccache,				   NULL,				   NULL,				   delegated_cred_handle);	if (ret != GSS_S_COMPLETE)	    goto out;	handle = (gsskrb5_cred) *delegated_cred_handle;    	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;	krb5_cc_close(context, ccache);	ccache = NULL;    }out:    if (ccache) {	/* Don't destroy the default cred cache */	if (delegated_cred_handle == NULL)	    krb5_cc_close(context, ccache);	else	    krb5_cc_destroy(context, ccache);    }    return ret;}static OM_uint32gsskrb5_acceptor_ready(OM_uint32 * minor_status,		       gsskrb5_ctx ctx,		       krb5_context context,		       gss_cred_id_t *delegated_cred_handle){    OM_uint32 ret;    int32_t seq_number;    int is_cfx = 0;    krb5_auth_getremoteseqnumber (context,				  ctx->auth_context,				  &seq_number);    _gsskrb5i_is_cfx(ctx, &is_cfx);    ret = _gssapi_msg_order_create(minor_status,				   &ctx->order,				   _gssapi_msg_order_f(ctx->flags),				   seq_number, 0, is_cfx);    if (ret)	return ret;    /*      * If requested, set local sequence num to remote sequence if this     * isn't a mutual authentication context     */    if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) {	krb5_auth_con_setlocalseqnumber(context,					ctx->auth_context,					seq_number);    }    /*     * We should handle the delegation ticket, in case it's there     */    if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) {	ret = gsskrb5_accept_delegated_token(minor_status,					     ctx,					     context,					     delegated_cred_handle);	if (ret)	    return ret;    } else {	/* Well, looks like it wasn't there after all */	ctx->flags &= ~GSS_C_DELEG_FLAG;    }    ctx->state = ACCEPTOR_READY;    ctx->more_flags |= OPEN;    return GSS_S_COMPLETE;}static OM_uint32gsskrb5_acceptor_start(OM_uint32 * minor_status,		       gsskrb5_ctx ctx,		       krb5_context context,		       const gss_cred_id_t acceptor_cred_handle,		       const gss_buffer_t input_token_buffer,		       const gss_channel_bindings_t input_chan_bindings,		       gss_name_t * src_name,		       gss_OID * mech_type,		       gss_buffer_t output_token,		       OM_uint32 * ret_flags,		       OM_uint32 * time_rec,		       gss_cred_id_t * delegated_cred_handle){    krb5_error_code kret;    OM_uint32 ret = GSS_S_COMPLETE;    krb5_data indata;    krb5_flags ap_options;    krb5_keytab keytab = NULL;    int is_cfx = 0;    const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle;    /*     * We may, or may not, have an escapsulation.     */    ret = _gsskrb5_decapsulate (minor_status,				input_token_buffer,				&indata,				"\x01\x00",				GSS_KRB5_MECHANISM);    if (ret) {	/* Assume that there is no OID wrapping. */	indata.length	= input_token_buffer->length;	indata.data	= input_token_buffer->value;    }    /*     * We need to get our keytab     */    if (acceptor_cred == NULL) {	if (_gsskrb5_keytab != NULL)	    keytab = _gsskrb5_keytab;    } else if (acceptor_cred->keytab != NULL) {	keytab = acceptor_cred->keytab;    }        /*     * We need to check the ticket and create the AP-REP packet     */    {	krb5_rd_req_in_ctx in = NULL;	krb5_rd_req_out_ctx out = NULL;	kret = krb5_rd_req_in_ctx_alloc(context, &in);	if (kret == 0)	    kret = krb5_rd_req_in_set_keytab(context, in, keytab);	if (kret) {	    if (in)		krb5_rd_req_in_ctx_free(context, in);	    ret = GSS_S_FAILURE;	    *minor_status = kret;	    return ret;	}	kret = krb5_rd_req_ctx(context,			       &ctx->auth_context,			       &indata,			       (acceptor_cred_handle == GSS_C_NO_CREDENTIAL) ? NULL : acceptor_cred->principal,			       in, &out);	krb5_rd_req_in_ctx_free(context, in);	if (kret) {	    ret = GSS_S_FAILURE;	    *minor_status = kret;	    return ret;	}	/*	 * We need to remember some data on the context_handle.	 */	kret = krb5_rd_req_out_get_ap_req_options(context, out,						  &ap_options);	if (kret == 0)	    kret = krb5_rd_req_out_get_ticket(context, out, 					      &ctx->ticket);	if (kret == 0)	    kret = krb5_rd_req_out_get_keyblock(context, out,						&ctx->service_keyblock);	ctx->lifetime = ctx->ticket->ticket.endtime;	krb5_rd_req_out_ctx_free(context, out);	if (kret) {	    ret = GSS_S_FAILURE;	    *minor_status = kret;	    return ret;	}    }            /*     * We need to copy the principal names to the context and the     * calling layer.     */    kret = krb5_copy_principal(context,			       ctx->ticket->client,			       &ctx->source);    if (kret) {	ret = GSS_S_FAILURE;	*minor_status = kret;    }    kret = krb5_copy_principal(context, 			       ctx->ticket->server,			       &ctx->target);    if (kret) {	ret = GSS_S_FAILURE;	*minor_status = kret;	return ret;    }        /*     * We need to setup some compat stuff, this assumes that     * context_handle->target is already set.     */    ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);    if (ret)	return ret;    if (src_name != NULL) {	kret = krb5_copy_principal (context,				    ctx->ticket->client,				    (gsskrb5_name*)src_name);	if (kret) {	    ret = GSS_S_FAILURE;	    *minor_status = kret;	    return ret;	}    }    /*     * We need to get the flags out of the 8003 checksum.     */    {	krb5_authenticator authenticator;      	kret = krb5_auth_con_getauthenticator(context,					      ctx->auth_context,					      &authenticator);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?