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 + -
显示快捷键?