From 19d0fde1ace012e366182b511c528f7ab6a0ed37 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 20 Jun 2024 06:07:27 +0200 Subject: Merging upstream version 2:4.20.2+dfsg. Signed-off-by: Daniel Baumann --- libcli/nbt/libnbt.h | 3 ++ libcli/nbt/nbtsocket.c | 44 ++++++++++++++++++++ libcli/security/dom_sid.c | 14 ++++--- libcli/smb/smbXcli_base.c | 104 +++++++++++++++++++++++++++++++++++++++++++--- libcli/smb/smbXcli_base.h | 5 +++ 5 files changed, 159 insertions(+), 11 deletions(-) (limited to 'libcli') diff --git a/libcli/nbt/libnbt.h b/libcli/nbt/libnbt.h index 204484b..6a30c9f 100644 --- a/libcli/nbt/libnbt.h +++ b/libcli/nbt/libnbt.h @@ -331,6 +331,9 @@ NTSTATUS nbt_set_unexpected_handler(struct nbt_name_socket *nbtsock, void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, struct socket_address *), void *private_data); +NTSTATUS nbt_name_send_raw(struct nbt_name_socket *nbtsock, + struct socket_address *dest, + const DATA_BLOB pkt_blob); NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, struct socket_address *dest, struct nbt_name_packet *request); diff --git a/libcli/nbt/nbtsocket.c b/libcli/nbt/nbtsocket.c index 47e73cf..b2945ad 100644 --- a/libcli/nbt/nbtsocket.c +++ b/libcli/nbt/nbtsocket.c @@ -448,6 +448,50 @@ failed: return NULL; } +/* + send off a nbt name packet +*/ +_PUBLIC_ NTSTATUS nbt_name_send_raw(struct nbt_name_socket *nbtsock, + struct socket_address *dest, + const DATA_BLOB pkt_blob) +{ + struct nbt_name_request *req; + + req = talloc_zero(nbtsock, struct nbt_name_request); + NT_STATUS_HAVE_NO_MEMORY(req); + + req->nbtsock = nbtsock; + req->dest = socket_address_copy(req, dest); + if (req->dest == NULL) { + goto failed; + } + req->state = NBT_REQUEST_SEND; + /* + * We don't expect a response so + * just pretent it is a request, + * but we really don't care about the + * content. + */ + req->is_reply = true; + + req->encoded = data_blob_dup_talloc(req, pkt_blob); + if (req->encoded.length != pkt_blob.length) { + goto failed; + } + + talloc_set_destructor(req, nbt_name_request_destructor); + + DLIST_ADD_END(nbtsock->send_queue, req); + + TEVENT_FD_WRITEABLE(nbtsock->fde); + + return NT_STATUS_OK; + +failed: + talloc_free(req); + return NT_STATUS_NO_MEMORY; +} + /* send off a nbt name reply diff --git a/libcli/security/dom_sid.c b/libcli/security/dom_sid.c index eaece2a..21012b7 100644 --- a/libcli/security/dom_sid.c +++ b/libcli/security/dom_sid.c @@ -28,6 +28,7 @@ #include "librpc/gen_ndr/security.h" #include "dom_sid.h" #include "lib/util/smb_strtox.h" +#include "lib/util/tsort.h" /***************************************************************** Compare the auth portion of two sids. @@ -46,11 +47,12 @@ int dom_sid_compare_auth(const struct dom_sid *sid1, return 1; if (sid1->sid_rev_num != sid2->sid_rev_num) - return sid1->sid_rev_num - sid2->sid_rev_num; + return NUMERIC_CMP(sid1->sid_rev_num, sid2->sid_rev_num); for (i = 0; i < 6; i++) - if (sid1->id_auth[i] != sid2->id_auth[i]) - return sid1->id_auth[i] - sid2->id_auth[i]; + if (sid1->id_auth[i] != sid2->id_auth[i]) { + return NUMERIC_CMP(sid1->id_auth[i], sid2->id_auth[i]); + } return 0; } @@ -71,9 +73,9 @@ int dom_sid_compare(const struct dom_sid *sid1, const struct dom_sid *sid2) return 1; /* Compare most likely different rids, first: i.e start at end */ - if (sid1->num_auths != sid2->num_auths) - return sid1->num_auths - sid2->num_auths; - + if (sid1->num_auths != sid2->num_auths) { + return NUMERIC_CMP(sid1->num_auths, sid2->num_auths); + } for (i = sid1->num_auths-1; i >= 0; --i) { if (sid1->sub_auths[i] < sid2->sub_auths[i]) { return -1; diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c index a52a615..87acddf 100644 --- a/libcli/smb/smbXcli_base.c +++ b/libcli/smb/smbXcli_base.c @@ -166,6 +166,13 @@ struct smb2cli_session { uint16_t channel_sequence; bool replay_active; bool require_signed_response; + + /* + * The following are just for torture tests + */ + bool anonymous_signing; + bool anonymous_encryption; + bool no_signing_disconnect; }; struct smbXcli_session { @@ -3999,6 +4006,9 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn, if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED) || NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED) || + (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && + session != NULL && + session->smb2->no_signing_disconnect) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) { /* * if the server returns @@ -4042,8 +4052,29 @@ static NTSTATUS smb2cli_conn_dispatch_incoming(struct smbXcli_conn *conn, /* * If the signing check fails, we disconnect * the connection. + * + * Unless + * smb2cli_session_torture_no_signing_disconnect + * was called in torture tests */ - return signing_status; + + if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + return signing_status; + } + + if (!NT_STATUS_EQUAL(status, signing_status)) { + return signing_status; + } + + if (session == NULL) { + return signing_status; + } + + if (!session->smb2->no_signing_disconnect) { + return signing_status; + } + + state->smb2.signing_skipped = true; } } @@ -6332,6 +6363,23 @@ void smb2cli_session_require_signed_response(struct smbXcli_session *session, session->smb2->require_signed_response = require_signed_response; } +void smb2cli_session_torture_anonymous_signing(struct smbXcli_session *session, + bool anonymous_signing) +{ + session->smb2->anonymous_signing = anonymous_signing; +} + +void smb2cli_session_torture_anonymous_encryption(struct smbXcli_session *session, + bool anonymous_encryption) +{ + session->smb2->anonymous_encryption = anonymous_encryption; +} + +void smb2cli_session_torture_no_signing_disconnect(struct smbXcli_session *session) +{ + session->smb2->no_signing_disconnect = true; +} + NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session, const struct iovec *iov) { @@ -6432,6 +6480,10 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, conn->protocol, preauth_hash); + if (session->smb2->anonymous_encryption) { + goto skip_signing_key; + } + status = smb2_signing_key_sign_create(session->smb2, conn->smb2.server.sign_algo, &_session_key, @@ -6441,6 +6493,15 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, return status; } + if (session->smb2->anonymous_signing) { + /* + * skip encryption and application keys + */ + goto skip_application_key; + } + +skip_signing_key: + status = smb2_signing_key_cipher_create(session->smb2, conn->smb2.server.cipher, &_session_key, @@ -6459,6 +6520,10 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, return status; } + if (session->smb2->anonymous_encryption) { + goto skip_application_key; + } + status = smb2_signing_key_sign_create(session->smb2, conn->smb2.server.sign_algo, &_session_key, @@ -6468,6 +6533,8 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, return status; } +skip_application_key: + status = smb2_signing_key_copy(session, session->smb2->signing_key, &session->smb2_channel.signing_key); @@ -6477,6 +6544,18 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, check_signature = conn->mandatory_signing; + if (conn->protocol >= PROTOCOL_SMB3_11) { + check_signature = true; + } + + if (session->smb2->anonymous_signing) { + check_signature = false; + } + + if (session->smb2->anonymous_encryption) { + check_signature = false; + } + hdr_flags = IVAL(recv_iov[0].iov_base, SMB2_HDR_FLAGS); if (hdr_flags & SMB2_HDR_FLAG_SIGNED) { /* @@ -6492,10 +6571,6 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, check_signature = true; } - if (conn->protocol >= PROTOCOL_SMB3_11) { - check_signature = true; - } - if (check_signature) { status = smb2_signing_check_pdu(session->smb2_channel.signing_key, recv_iov, 3); @@ -6527,6 +6602,15 @@ NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, session->smb2->should_encrypt = false; } + if (session->smb2->anonymous_signing) { + session->smb2->should_sign = true; + } + + if (session->smb2->anonymous_encryption) { + session->smb2->should_encrypt = true; + session->smb2->should_sign = false; + } + /* * CCM and GCM algorithms must never have their * nonce wrap, or the security of the whole @@ -6698,6 +6782,16 @@ NTSTATUS smb2cli_session_set_channel_key(struct smbXcli_session *session, NTSTATUS smb2cli_session_encryption_on(struct smbXcli_session *session) { + if (session->smb2->anonymous_signing) { + return NT_STATUS_INVALID_PARAMETER_MIX; + } + + if (session->smb2->anonymous_encryption) { + SMB_ASSERT(session->smb2->should_encrypt); + SMB_ASSERT(!session->smb2->should_sign); + return NT_STATUS_OK; + } + if (!session->smb2->should_sign) { /* * We need required signing on the session diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h index 25ccd84..69fa131 100644 --- a/libcli/smb/smbXcli_base.h +++ b/libcli/smb/smbXcli_base.h @@ -535,6 +535,11 @@ void smb2cli_session_start_replay(struct smbXcli_session *session); void smb2cli_session_stop_replay(struct smbXcli_session *session); void smb2cli_session_require_signed_response(struct smbXcli_session *session, bool require_signed_response); +void smb2cli_session_torture_anonymous_signing(struct smbXcli_session *session, + bool anonymous_signing); +void smb2cli_session_torture_anonymous_encryption(struct smbXcli_session *session, + bool anonymous_encryption); +void smb2cli_session_torture_no_signing_disconnect(struct smbXcli_session *session); NTSTATUS smb2cli_session_update_preauth(struct smbXcli_session *session, const struct iovec *iov); NTSTATUS smb2cli_session_set_session_key(struct smbXcli_session *session, -- cgit v1.2.3