DATA_BLOB version_blob = data_blob_null;
const unsigned int mic_len = NTLMSSP_MIC_SIZE;
DATA_BLOB mic_blob = data_blob_null;
+ const uint8_t zero_channel_bindings[16] = { 0, };
+ const uint8_t *client_channel_bindings = zero_channel_bindings;
+ uint8_t server_channel_bindings[16] = { 0, };
const char *parse_string;
bool ok;
struct timeval endtime;
uint32_t i = 0;
uint32_t count = 0;
const struct AV_PAIR *flags = NULL;
+ const struct AV_PAIR *cb = NULL;
const struct AV_PAIR *eol = NULL;
uint32_t av_flags = 0;
ntlmssp_state->new_spnego = true;
}
+ cb = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs,
+ MsvChannelBindings);
+ if (cb != NULL) {
+ client_channel_bindings = cb->Value.ChannelBindings;
+ }
+
count = ntlmssp_state->server.av_pair_list.count;
if (v2_resp.Challenge.AvPairs.count < count) {
return NT_STATUS_INVALID_PARAMETER;
}
}
+ if (gensec_security->channel_bindings != NULL) {
+ nt_status = ntlmssp_hash_channel_bindings(gensec_security,
+ server_channel_bindings);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ ok = mem_equal_const_time(client_channel_bindings,
+ server_channel_bindings,
+ 16);
+ if (!ok && gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL) {
+ /*
+ * Unlike kerberos, explicit 16 zeros in
+ * MsvChannelBindings are not enough to
+ * pass the optional check.
+ *
+ * So we only let it through without explicit
+ * MsvChannelBindings.
+ */
+ ok = (client_channel_bindings == zero_channel_bindings);
+ }
+ if (!ok) {
+ DBG_WARNING("Invalid channel bindings for "
+ "user=[%s] domain=[%s] workstation=[%s]\n",
+ ntlmssp_state->user,
+ ntlmssp_state->domain,
+ ntlmssp_state->client.netbios_name);
+ dump_data(DBGLVL_WARNING,
+ client_channel_bindings,
+ 16);
+ dump_data(DBGLVL_WARNING,
+ server_channel_bindings,
+ 16);
+ return NT_STATUS_BAD_BINDINGS;
+ }
+ }
+
nttime_to_timeval(&endtime, ntlmssp_state->server.challenge_endtime);
expired = timeval_expired(&endtime);
if (expired) {
*/
#include "includes.h"
+#include "auth/gensec/gensec.h"
+#include "auth/gensec/gensec_internal.h"
#include "../auth/ntlmssp/ntlmssp.h"
#include "../auth/ntlmssp/ntlmssp_private.h"
+#include "lib/crypto/gnutls_helpers.h"
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
return data_blob_const(version_buffer, ARRAY_SIZE(version_buffer));
}
+
+NTSTATUS ntlmssp_hash_channel_bindings(struct gensec_security *gensec_security,
+ uint8_t cb_hash[16])
+{
+ const struct gensec_channel_bindings *cb =
+ gensec_security->channel_bindings;
+ gnutls_hash_hd_t hash_hnd = NULL;
+ uint8_t uint32buf[4];
+ int rc;
+
+ if (cb == NULL) {
+ memset(cb_hash, 0, 16);
+ return NT_STATUS_OK;
+ }
+
+ GNUTLS_FIPS140_SET_LAX_MODE();
+ rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
+ if (rc < 0) {
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+
+ SIVAL(uint32buf, 0, cb->initiator_addrtype);
+ rc = gnutls_hash(hash_hnd, uint32buf, sizeof(uint32buf));
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ SIVAL(uint32buf, 0, cb->initiator_address.length);
+ rc = gnutls_hash(hash_hnd, uint32buf, sizeof(uint32buf));
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ if (cb->initiator_address.length > 0) {
+ rc = gnutls_hash(hash_hnd,
+ cb->initiator_address.data,
+ cb->initiator_address.length);
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ }
+ SIVAL(uint32buf, 0, cb->acceptor_addrtype);
+ rc = gnutls_hash(hash_hnd, uint32buf, sizeof(uint32buf));
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ SIVAL(uint32buf, 0, cb->acceptor_address.length);
+ rc = gnutls_hash(hash_hnd, uint32buf, sizeof(uint32buf));
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ if (cb->acceptor_address.length > 0) {
+ rc = gnutls_hash(hash_hnd,
+ cb->acceptor_address.data,
+ cb->acceptor_address.length);
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ }
+ SIVAL(uint32buf, 0, cb->application_data.length);
+ rc = gnutls_hash(hash_hnd, uint32buf, sizeof(uint32buf));
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ if (cb->application_data.length > 0) {
+ rc = gnutls_hash(hash_hnd,
+ cb->application_data.data,
+ cb->application_data.length);
+ if (rc < 0) {
+ gnutls_hash_deinit(hash_hnd, NULL);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
+ }
+ }
+
+ gnutls_hash_deinit(hash_hnd, cb_hash);
+ GNUTLS_FIPS140_SET_STRICT_MODE();
+ return NT_STATUS_OK;
+}