cfx.c

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

C
879
字号
	free_Checksum(&cksum);    }    krb5_crypto_destroy(context, crypto);    if (conf_state != NULL) {	*conf_state = conf_req_flag;    }    *minor_status = 0;    return GSS_S_COMPLETE;}OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,			     const gsskrb5_ctx context_handle,			     krb5_context context,			     const gss_buffer_t input_message_buffer,			     gss_buffer_t output_message_buffer,			     int *conf_state,			     gss_qop_t *qop_state,			     krb5_keyblock *key){    krb5_crypto crypto;    gss_cfx_wrap_token token;    u_char token_flags;    krb5_error_code ret;    unsigned usage;    krb5_data data;    uint16_t ec, rrc;    OM_uint32 seq_number_lo, seq_number_hi;    size_t len;    u_char *p;    *minor_status = 0;    if (input_message_buffer->length < sizeof(*token)) {	return GSS_S_DEFECTIVE_TOKEN;    }    p = input_message_buffer->value;    token = (gss_cfx_wrap_token)p;    if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) {	return GSS_S_DEFECTIVE_TOKEN;    }    /* Ignore unknown flags */    token_flags = token->Flags &	(CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey);    if (token_flags & CFXSentByAcceptor) {	if ((context_handle->more_flags & LOCAL) == 0)	    return GSS_S_DEFECTIVE_TOKEN;    }    if (context_handle->more_flags & ACCEPTOR_SUBKEY) {	if ((token_flags & CFXAcceptorSubkey) == 0)	    return GSS_S_DEFECTIVE_TOKEN;    } else {	if (token_flags & CFXAcceptorSubkey)	    return GSS_S_DEFECTIVE_TOKEN;    }    if (token->Filler != 0xFF) {	return GSS_S_DEFECTIVE_TOKEN;    }    if (conf_state != NULL) {	*conf_state = (token_flags & CFXSealed) ? 1 : 0;    }    ec  = (token->EC[0]  << 8) | token->EC[1];    rrc = (token->RRC[0] << 8) | token->RRC[1];    /*     * Check sequence number     */    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);    if (seq_number_hi) {	/* no support for 64-bit sequence numbers */	*minor_status = ERANGE;	return GSS_S_UNSEQ_TOKEN;    }    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);    ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo);    if (ret != 0) {	*minor_status = 0;	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);	_gsskrb5_release_buffer(minor_status, output_message_buffer);	return ret;    }    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);    /*     * Decrypt and/or verify checksum     */    ret = krb5_crypto_init(context, key, 0, &crypto);    if (ret != 0) {	*minor_status = ret;	return GSS_S_FAILURE;    }    if (context_handle->more_flags & LOCAL) {	usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;    } else {	usage = KRB5_KU_USAGE_INITIATOR_SEAL;    }    p += sizeof(*token);    len = input_message_buffer->length;    len -= (p - (u_char *)input_message_buffer->value);    /* Rotate by RRC; bogus to do this in-place XXX */    *minor_status = rrc_rotate(p, len, rrc, TRUE);    if (*minor_status != 0) {	krb5_crypto_destroy(context, crypto);	return GSS_S_FAILURE;    }    if (token_flags & CFXSealed) {	ret = krb5_decrypt(context, crypto, usage,	    p, len, &data);	if (ret != 0) {	    *minor_status = ret;	    krb5_crypto_destroy(context, crypto);	    return GSS_S_BAD_MIC;	}	/* Check that there is room for the pad and token header */	if (data.length < ec + sizeof(*token)) {	    krb5_crypto_destroy(context, crypto);	    krb5_data_free(&data);	    return GSS_S_DEFECTIVE_TOKEN;	}	p = data.data;	p += data.length - sizeof(*token);	/* RRC is unprotected; don't modify input buffer */	((gss_cfx_wrap_token)p)->RRC[0] = token->RRC[0];	((gss_cfx_wrap_token)p)->RRC[1] = token->RRC[1];	/* Check the integrity of the header */	if (memcmp(p, token, sizeof(*token)) != 0) {	    krb5_crypto_destroy(context, crypto);	    krb5_data_free(&data);	    return GSS_S_BAD_MIC;	}	output_message_buffer->value = data.data;	output_message_buffer->length = data.length - ec - sizeof(*token);    } else {	Checksum cksum;	/* Determine checksum type */	ret = krb5_crypto_get_checksum_type(context,					    crypto, &cksum.cksumtype);	if (ret != 0) {	    *minor_status = ret;	    krb5_crypto_destroy(context, crypto);	    return GSS_S_FAILURE;	}	cksum.checksum.length = ec;	/* Check we have at least as much data as the checksum */	if (len < cksum.checksum.length) {	    *minor_status = ERANGE;	    krb5_crypto_destroy(context, crypto);	    return GSS_S_BAD_MIC;	}	/* Length now is of the plaintext only, no checksum */	len -= cksum.checksum.length;	cksum.checksum.data = p + len;	output_message_buffer->length = len; /* for later */	output_message_buffer->value = malloc(len + sizeof(*token));	if (output_message_buffer->value == NULL) {	    *minor_status = ENOMEM;	    krb5_crypto_destroy(context, crypto);	    return GSS_S_FAILURE;	}	/* Checksum is over (plaintext-data | "header") */	memcpy(output_message_buffer->value, p, len);	memcpy((u_char *)output_message_buffer->value + len, 	       token, sizeof(*token));	/* EC is not included in checksum calculation */	token = (gss_cfx_wrap_token)((u_char *)output_message_buffer->value +				     len);	token->EC[0]  = 0;	token->EC[1]  = 0;	token->RRC[0] = 0;	token->RRC[1] = 0;	ret = krb5_verify_checksum(context, crypto,				   usage,				   output_message_buffer->value,				   len + sizeof(*token),				   &cksum);	if (ret != 0) {	    *minor_status = ret;	    krb5_crypto_destroy(context, crypto);	    _gsskrb5_release_buffer(minor_status, output_message_buffer);	    return GSS_S_BAD_MIC;	}    }    krb5_crypto_destroy(context, crypto);    if (qop_state != NULL) {	*qop_state = GSS_C_QOP_DEFAULT;    }    *minor_status = 0;    return GSS_S_COMPLETE;}OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,			  const gsskrb5_ctx context_handle,			  krb5_context context,			  gss_qop_t qop_req,			  const gss_buffer_t message_buffer,			  gss_buffer_t message_token,			  krb5_keyblock *key){    krb5_crypto crypto;    gss_cfx_mic_token token;    krb5_error_code ret;    unsigned usage;    Checksum cksum;    u_char *buf;    size_t len;    int32_t seq_number;    ret = krb5_crypto_init(context, key, 0, &crypto);    if (ret != 0) {	*minor_status = ret;	return GSS_S_FAILURE;    }    len = message_buffer->length + sizeof(*token);    buf = malloc(len);    if (buf == NULL) {	*minor_status = ENOMEM;	krb5_crypto_destroy(context, crypto);	return GSS_S_FAILURE;    }    memcpy(buf, message_buffer->value, message_buffer->length);    token = (gss_cfx_mic_token)(buf + message_buffer->length);    token->TOK_ID[0] = 0x04;    token->TOK_ID[1] = 0x04;    token->Flags = 0;    if ((context_handle->more_flags & LOCAL) == 0)	token->Flags |= CFXSentByAcceptor;    if (context_handle->more_flags & ACCEPTOR_SUBKEY)	token->Flags |= CFXAcceptorSubkey;    memset(token->Filler, 0xFF, 5);    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);    krb5_auth_con_getlocalseqnumber(context,				    context_handle->auth_context,				    &seq_number);    _gsskrb5_encode_be_om_uint32(0,          &token->SND_SEQ[0]);    _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);    krb5_auth_con_setlocalseqnumber(context,				    context_handle->auth_context,				    ++seq_number);    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);    if (context_handle->more_flags & LOCAL) {	usage = KRB5_KU_USAGE_INITIATOR_SIGN;    } else {	usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;    }    ret = krb5_create_checksum(context, crypto,	usage, 0, buf, len, &cksum);    if (ret != 0) {	*minor_status = ret;	krb5_crypto_destroy(context, crypto);	free(buf);	return GSS_S_FAILURE;    }    krb5_crypto_destroy(context, crypto);    /* Determine MIC length */    message_token->length = sizeof(*token) + cksum.checksum.length;    message_token->value = malloc(message_token->length);    if (message_token->value == NULL) {	*minor_status = ENOMEM;	free_Checksum(&cksum);	free(buf);	return GSS_S_FAILURE;    }    /* Token is { "header" | get_mic("header" | plaintext-data) } */    memcpy(message_token->value, token, sizeof(*token));    memcpy((u_char *)message_token->value + sizeof(*token),	   cksum.checksum.data, cksum.checksum.length);    free_Checksum(&cksum);    free(buf);    *minor_status = 0;    return GSS_S_COMPLETE;}OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,				 const gsskrb5_ctx context_handle,				 krb5_context context,				 const gss_buffer_t message_buffer,				 const gss_buffer_t token_buffer,				 gss_qop_t *qop_state,				 krb5_keyblock *key){    krb5_crypto crypto;    gss_cfx_mic_token token;    u_char token_flags;    krb5_error_code ret;    unsigned usage;    OM_uint32 seq_number_lo, seq_number_hi;    u_char *buf, *p;    Checksum cksum;    *minor_status = 0;    if (token_buffer->length < sizeof(*token)) {	return GSS_S_DEFECTIVE_TOKEN;    }    p = token_buffer->value;    token = (gss_cfx_mic_token)p;    if (token->TOK_ID[0] != 0x04 || token->TOK_ID[1] != 0x04) {	return GSS_S_DEFECTIVE_TOKEN;    }    /* Ignore unknown flags */    token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey);    if (token_flags & CFXSentByAcceptor) {	if ((context_handle->more_flags & LOCAL) == 0)	    return GSS_S_DEFECTIVE_TOKEN;    }    if (context_handle->more_flags & ACCEPTOR_SUBKEY) {	if ((token_flags & CFXAcceptorSubkey) == 0)	    return GSS_S_DEFECTIVE_TOKEN;    } else {	if (token_flags & CFXAcceptorSubkey)	    return GSS_S_DEFECTIVE_TOKEN;    }    if (memcmp(token->Filler, "\xff\xff\xff\xff\xff", 5) != 0) {	return GSS_S_DEFECTIVE_TOKEN;    }    /*     * Check sequence number     */    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);    if (seq_number_hi) {	*minor_status = ERANGE;	return GSS_S_UNSEQ_TOKEN;    }    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);    ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo);    if (ret != 0) {	*minor_status = 0;	HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);	return ret;    }    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);    /*     * Verify checksum     */    ret = krb5_crypto_init(context, key, 0, &crypto);    if (ret != 0) {	*minor_status = ret;	return GSS_S_FAILURE;    }    ret = krb5_crypto_get_checksum_type(context, crypto,					&cksum.cksumtype);    if (ret != 0) {	*minor_status = ret;	krb5_crypto_destroy(context, crypto);	return GSS_S_FAILURE;    }    cksum.checksum.data = p + sizeof(*token);    cksum.checksum.length = token_buffer->length - sizeof(*token);    if (context_handle->more_flags & LOCAL) {	usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;    } else {	usage = KRB5_KU_USAGE_INITIATOR_SIGN;    }    buf = malloc(message_buffer->length + sizeof(*token));    if (buf == NULL) {	*minor_status = ENOMEM;	krb5_crypto_destroy(context, crypto);	return GSS_S_FAILURE;    }    memcpy(buf, message_buffer->value, message_buffer->length);    memcpy(buf + message_buffer->length, token, sizeof(*token));    ret = krb5_verify_checksum(context, crypto,			       usage,			       buf,			       sizeof(*token) + message_buffer->length,			       &cksum);    krb5_crypto_destroy(context, crypto);    if (ret != 0) {	*minor_status = ret;	free(buf);	return GSS_S_BAD_MIC;    }    free(buf);    if (qop_state != NULL) {	*qop_state = GSS_C_QOP_DEFAULT;    }    return GSS_S_COMPLETE;}

⌨️ 快捷键说明

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