accept_sec_context.c

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

C
802
字号
	if(kret) {	    ret = GSS_S_FAILURE;	    *minor_status = kret;	    return ret;	}        if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) {            ret = _gsskrb5_verify_8003_checksum(minor_status,						input_chan_bindings,						authenticator->cksum,						&ctx->flags,						&ctx->fwd_data);	    krb5_free_authenticator(context, &authenticator);	    if (ret) {		return ret;	    }        } else {	    krb5_crypto crypto;	    kret = krb5_crypto_init(context, 				    ctx->auth_context->keyblock, 				    0, &crypto);	    if(kret) {		krb5_free_authenticator(context, &authenticator);		ret = GSS_S_FAILURE;		*minor_status = kret;		return ret;	    }	    /* 	     * Windows accepts Samba3's use of a kerberos, rather than	     * GSSAPI checksum here 	     */	    kret = krb5_verify_checksum(context,					crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0,					authenticator->cksum);	    krb5_free_authenticator(context, &authenticator);	    krb5_crypto_destroy(context, crypto);	    if(kret) {		ret = GSS_S_BAD_SIG;		*minor_status = kret;		return ret;	    }	    /* 	     * Samba style get some flags (but not DCE-STYLE)	     */	    ctx->flags = 		GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;        }    }        if(ctx->flags & GSS_C_MUTUAL_FLAG) {	krb5_data outbuf;	    	_gsskrb5i_is_cfx(ctx, &is_cfx);	    	if (is_cfx != 0 	    || (ap_options & AP_OPTS_USE_SUBKEY)) {	    kret = krb5_auth_con_addflags(context,					  ctx->auth_context,					  KRB5_AUTH_CONTEXT_USE_SUBKEY,					  NULL);	    ctx->more_flags |= ACCEPTOR_SUBKEY;	}	    	kret = krb5_mk_rep(context,			   ctx->auth_context,			   &outbuf);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}	    	if (IS_DCE_STYLE(ctx)) {	    output_token->length = outbuf.length;	    output_token->value = outbuf.data;	} else {	    ret = _gsskrb5_encapsulate(minor_status,				       &outbuf,				       output_token,				       "\x02\x00",				       GSS_KRB5_MECHANISM);	    krb5_data_free (&outbuf);	    if (ret)		return ret;	}    }        ctx->flags |= GSS_C_TRANS_FLAG;    /* Remember the flags */        ctx->lifetime = ctx->ticket->ticket.endtime;    ctx->more_flags |= OPEN;        if (mech_type)	*mech_type = GSS_KRB5_MECHANISM;        if (time_rec) {	ret = _gsskrb5_lifetime_left(minor_status,				     context,				     ctx->lifetime,				     time_rec);	if (ret) {	    return ret;	}    }    /*     * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from     * the client.     */    if (IS_DCE_STYLE(ctx)) {	/*	 * Return flags to caller, but we haven't processed	 * delgations yet	 */	if (ret_flags)	    *ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG);	ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE;	return GSS_S_CONTINUE_NEEDED;    }    ret = gsskrb5_acceptor_ready(minor_status, ctx, context, 				 delegated_cred_handle);    if (ret_flags)	*ret_flags = ctx->flags;    return ret;}static OM_uint32acceptor_wait_for_dcestyle(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){    OM_uint32 ret;    krb5_error_code kret;    krb5_data inbuf;    int32_t r_seq_number, l_seq_number;	    /*      * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP     */    inbuf.length = input_token_buffer->length;    inbuf.data = input_token_buffer->value;    /*      * We need to remeber the old remote seq_number, then check if the     * client has replied with our local seq_number, and then reset     * the remote seq_number to the old value     */    {	kret = krb5_auth_con_getlocalseqnumber(context,					       ctx->auth_context,					       &l_seq_number);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}	kret = krb5_auth_getremoteseqnumber(context,					    ctx->auth_context,					    &r_seq_number);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}	kret = krb5_auth_con_setremoteseqnumber(context,						ctx->auth_context,						l_seq_number);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}    }    /*      * We need to verify the AP_REP, but we need to flag that this is     * DCE_STYLE, so don't check the timestamps this time, but put the     * flag DO_TIME back afterward.    */     {	krb5_ap_rep_enc_part *repl;	int32_t auth_flags;			krb5_auth_con_removeflags(context,				  ctx->auth_context,				  KRB5_AUTH_CONTEXT_DO_TIME,				  &auth_flags);	kret = krb5_rd_rep(context, ctx->auth_context, &inbuf, &repl);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}	krb5_free_ap_rep_enc_part(context, repl);	krb5_auth_con_setflags(context, ctx->auth_context, auth_flags);    }    /* We need to check the liftime */    {	OM_uint32 lifetime_rec;	ret = _gsskrb5_lifetime_left(minor_status,				     context,				     ctx->lifetime,				     &lifetime_rec);	if (ret) {	    return ret;	}	if (lifetime_rec == 0) {	    return GSS_S_CONTEXT_EXPIRED;	}		if (time_rec) *time_rec = lifetime_rec;    }    /* We need to give the caller the flags which are in use */    if (ret_flags) *ret_flags = ctx->flags;    if (src_name) {	kret = krb5_copy_principal(context,				   ctx->source,				   (gsskrb5_name*)src_name);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}    }    /*     * After the krb5_rd_rep() the remote and local seq_number should     * be the same, because the client just replies the seq_number     * from our AP-REP in its AP-REP, but then the client uses the     * seq_number from its AP-REQ for GSS_wrap()     */    {	int32_t tmp_r_seq_number, tmp_l_seq_number;	kret = krb5_auth_getremoteseqnumber(context,					    ctx->auth_context,					    &tmp_r_seq_number);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}	kret = krb5_auth_con_getlocalseqnumber(context,					       ctx->auth_context,					       &tmp_l_seq_number);	if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}	/*	 * Here we check if the client has responsed with our local seq_number,	 */	if (tmp_r_seq_number != tmp_l_seq_number) {	    return GSS_S_UNSEQ_TOKEN;	}    }    /*     * We need to reset the remote seq_number, because the client will use,     * the old one for the GSS_wrap() calls     */    {	kret = krb5_auth_con_setremoteseqnumber(context,						ctx->auth_context,						r_seq_number);		if (kret) {	    *minor_status = kret;	    return GSS_S_FAILURE;	}    }    return gsskrb5_acceptor_ready(minor_status, ctx, context, 				  delegated_cred_handle);}OM_uint32_gsskrb5_accept_sec_context(OM_uint32 * minor_status,			    gss_ctx_id_t * context_handle,			    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_context context;    OM_uint32 ret;    gsskrb5_ctx ctx;    GSSAPI_KRB5_INIT(&context);    output_token->length = 0;    output_token->value = NULL;    if (src_name != NULL)	*src_name = NULL;    if (mech_type)	*mech_type = GSS_KRB5_MECHANISM;    if (*context_handle == GSS_C_NO_CONTEXT) {	ret = _gsskrb5_create_ctx(minor_status,				  context_handle,				  context,				  input_chan_bindings,				  ACCEPTOR_START);	if (ret)	    return ret;    }        ctx = (gsskrb5_ctx)*context_handle;        /*     * TODO: check the channel_bindings      * (above just sets them to krb5 layer)     */    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);        switch (ctx->state) {    case ACCEPTOR_START:	ret = gsskrb5_acceptor_start(minor_status,				     ctx,				     context,				     acceptor_cred_handle,				     input_token_buffer,				     input_chan_bindings,				     src_name,				     mech_type,				     output_token,				     ret_flags,				     time_rec,				     delegated_cred_handle);	break;    case ACCEPTOR_WAIT_FOR_DCESTYLE:	ret = acceptor_wait_for_dcestyle(minor_status,					 ctx,					 context,					 acceptor_cred_handle,					 input_token_buffer,					 input_chan_bindings,					 src_name,					 mech_type,					 output_token,					 ret_flags,					 time_rec,					 delegated_cred_handle);	break;    case ACCEPTOR_READY:	/* 	 * If we get there, the caller have called	 * gss_accept_sec_context() one time too many.	 */	ret =  GSS_S_BAD_STATUS;	break;    default:	/* TODO: is this correct here? --metze */	ret =  GSS_S_BAD_STATUS;	break;    }        HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);        if (GSS_ERROR(ret)) {	OM_uint32 min2;	_gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER);    }    return ret;}

⌨️ 快捷键说明

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