summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcli/smb/smbXcli_base.c140
-rw-r--r--libcli/smb/smbXcli_base.h12
2 files changed, 152 insertions, 0 deletions
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index e792247727..2cb5d449d9 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -24,6 +24,7 @@
#include "../lib/util/tevent_ntstatus.h"
#include "../lib/util/tevent_unix.h"
#include "lib/util/util_net.h"
+#include "lib/util/dlinklist.h"
#include "../libcli/smb/smb_common.h"
#include "../libcli/smb/smb_seal.h"
#include "../libcli/smb/smb_signing.h"
@@ -31,6 +32,10 @@
#include "smbXcli_base.h"
#include "librpc/ndr/libndr.h"
+struct smbXcli_conn;
+struct smbXcli_req;
+struct smbXcli_session;
+
struct smbXcli_conn {
int fd;
struct sockaddr_storage local_ss;
@@ -114,6 +119,21 @@ struct smbXcli_conn {
uint16_t cur_credits;
uint16_t max_credits;
} smb2;
+
+ struct smbXcli_session *sessions;
+};
+
+struct smbXcli_session {
+ struct smbXcli_session *prev, *next;
+ struct smbXcli_conn *conn;
+
+ struct {
+ uint64_t session_id;
+ uint16_t session_flags;
+ DATA_BLOB signing_key;
+ DATA_BLOB session_key;
+ bool should_sign;
+ } smb2;
};
struct smbXcli_req_state {
@@ -178,6 +198,11 @@ static int smbXcli_conn_destructor(struct smbXcli_conn *conn)
*/
smbXcli_conn_disconnect(conn, NT_STATUS_OK);
+ while (conn->sessions) {
+ conn->sessions->conn = NULL;
+ DLIST_REMOVE(conn->sessions, conn->sessions);
+ }
+
if (conn->smb1.trans_enc) {
common_free_encryption_state(&conn->smb1.trans_enc);
}
@@ -3391,3 +3416,118 @@ NTSTATUS smbXcli_negprot(struct smbXcli_conn *conn,
TALLOC_FREE(frame);
return status;
}
+
+static int smbXcli_session_destructor(struct smbXcli_session *session)
+{
+ if (session->conn == NULL) {
+ return 0;
+ }
+
+ DLIST_REMOVE(session->conn->sessions, session);
+ return 0;
+}
+
+struct smbXcli_session *smbXcli_session_create(TALLOC_CTX *mem_ctx,
+ struct smbXcli_conn *conn)
+{
+ struct smbXcli_session *session;
+
+ session = talloc_zero(mem_ctx, struct smbXcli_session);
+ if (session == NULL) {
+ return NULL;
+ }
+ talloc_set_destructor(session, smbXcli_session_destructor);
+
+ DLIST_ADD_END(conn->sessions, session, struct smbXcli_session *);
+ session->conn = conn;
+
+ return session;
+}
+
+uint8_t smb2cli_session_security_mode(struct smbXcli_session *session)
+{
+ struct smbXcli_conn *conn = session->conn;
+ uint8_t security_mode = 0;
+
+ if (conn == NULL) {
+ return security_mode;
+ }
+
+ security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
+ if (conn->mandatory_signing) {
+ security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
+ }
+
+ return security_mode;
+}
+
+uint64_t smb2cli_session_current_id(struct smbXcli_session *session)
+{
+ return session->smb2.session_id;
+}
+
+void smb2cli_session_set_id_and_flags(struct smbXcli_session *session,
+ uint64_t session_id,
+ uint16_t session_flags)
+{
+ session->smb2.session_id = session_id;
+ session->smb2.session_flags = session_flags;
+}
+
+NTSTATUS smb2cli_session_update_session_key(struct smbXcli_session *session,
+ const DATA_BLOB session_key,
+ const struct iovec *recv_iov)
+{
+ struct smbXcli_conn *conn = session->conn;
+ uint16_t no_sign_flags;
+ DATA_BLOB signing_key;
+ NTSTATUS status;
+
+ if (conn == NULL) {
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+
+ no_sign_flags = SMB2_SESSION_FLAG_IS_GUEST | SMB2_SESSION_FLAG_IS_NULL;
+
+ if (session->smb2.session_flags & no_sign_flags) {
+ session->smb2.should_sign = false;
+ return NT_STATUS_OK;
+ }
+
+ if (session->smb2.signing_key.length > 0) {
+ signing_key = session->smb2.signing_key;
+ } else {
+ signing_key = session_key;
+ }
+
+ status = smb2_signing_check_pdu(signing_key, recv_iov, 3);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ session->smb2.session_key = data_blob_dup_talloc(session, session_key);
+ if (session->smb2.session_key.data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (session->smb2.signing_key.length > 0) {
+ return NT_STATUS_OK;
+ }
+
+ session->smb2.signing_key = data_blob_dup_talloc(session, signing_key);
+ if (session->smb2.signing_key.data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ session->smb2.should_sign = false;
+
+ if (conn->desire_signing) {
+ session->smb2.should_sign = true;
+ }
+
+ if (conn->smb2.server.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
+ session->smb2.should_sign = true;
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index df34d6c894..c64e3bad2f 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -22,6 +22,7 @@
#define _SMBXCLI_BASE_H_
struct smbXcli_conn;
+struct smbXcli_session;
struct smb_trans_enc_state;
struct GUID;
@@ -193,4 +194,15 @@ NTSTATUS smbXcli_negprot(struct smbXcli_conn *conn,
enum protocol_types min_protocol,
enum protocol_types max_protocol);
+struct smbXcli_session *smbXcli_session_create(TALLOC_CTX *mem_ctx,
+ struct smbXcli_conn *conn);
+uint8_t smb2cli_session_security_mode(struct smbXcli_session *session);
+uint64_t smb2cli_session_current_id(struct smbXcli_session *session);
+void smb2cli_session_set_id_and_flags(struct smbXcli_session *session,
+ uint64_t session_id,
+ uint16_t session_flags);
+NTSTATUS smb2cli_session_update_session_key(struct smbXcli_session *session,
+ const DATA_BLOB session_key,
+ const struct iovec *recv_iov);
+
#endif /* _SMBXCLI_BASE_H_ */