summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2014-06-24 00:22:30 +0200
committerStefan Metzmacher <metze@samba.org>2014-07-24 19:07:06 +0200
commit720189f246c33c763882731e626c5b0fe558d0f9 (patch)
tree372962e6517ef6a1509b57e7fc498307253b64d5
parent78e46d7349b5839993c001a5afc2060a48244d15 (diff)
downloadsamba-720189f246c33c763882731e626c5b0fe558d0f9.tar.gz
samba-720189f246c33c763882731e626c5b0fe558d0f9.tar.xz
samba-720189f246c33c763882731e626c5b0fe558d0f9.zip
s4:libcli/smb2: add smb2_session_channel()
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Volker Lendecke <vl@samba.org>
-rw-r--r--source4/libcli/smb2/session.c83
-rw-r--r--source4/libcli/smb2/smb2.h1
2 files changed, 74 insertions, 10 deletions
diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c
index 4d1402a09b..9ab96a3a13 100644
--- a/source4/libcli/smb2/session.c
+++ b/source4/libcli/smb2/session.c
@@ -66,11 +66,54 @@ struct smb2_session *smb2_session_init(struct smb2_transport *transport,
return session;
}
+/*
+ * Note: that the caller needs to keep 'transport' around as
+ * long as the returned session is active!
+ */
+struct smb2_session *smb2_session_channel(struct smb2_transport *transport,
+ struct gensec_settings *settings,
+ TALLOC_CTX *parent_ctx,
+ struct smb2_session *base_session)
+{
+ struct smb2_session *session;
+ NTSTATUS status;
+
+ session = talloc_zero(parent_ctx, struct smb2_session);
+ if (!session) {
+ return NULL;
+ }
+ session->transport = transport;
+
+ status = smb2cli_session_create_channel(session,
+ base_session->smbXcli,
+ transport->conn,
+ &session->smbXcli);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(session);
+ return NULL;
+ }
+
+ session->needs_bind = true;
+
+ /* prepare a gensec context for later use */
+ status = gensec_client_start(session, &session->gensec,
+ settings);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(session);
+ return NULL;
+ }
+
+ gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
+
+ return session;
+}
+
struct smb2_session_setup_spnego_state {
struct tevent_context *ev;
struct smb2_session *session;
struct cli_credentials *credentials;
uint64_t previous_session_id;
+ bool session_bind;
bool reauth;
NTSTATUS gensec_status;
DATA_BLOB in_secblob;
@@ -98,6 +141,7 @@ struct tevent_req *smb2_session_setup_spnego_send(
const DATA_BLOB *server_gss_blob;
DATA_BLOB negprot_secblob = data_blob_null;
uint32_t timeout_msec;
+ uint8_t in_flags = 0;
timeout_msec = session->transport->options.request_timeout * 1000;
@@ -112,10 +156,11 @@ struct tevent_req *smb2_session_setup_spnego_send(
state->previous_session_id = previous_session_id;
current_session_id = smb2cli_session_current_id(state->session->smbXcli);
- if (current_session_id != 0) {
+ if (state->session->needs_bind) {
+ state->session_bind = true;
+ } else if (current_session_id != 0) {
state->reauth = true;
}
-
server_gss_blob = smbXcli_conn_server_gss_blob(session->transport->conn);
if (server_gss_blob) {
negprot_secblob = *server_gss_blob;
@@ -158,11 +203,15 @@ struct tevent_req *smb2_session_setup_spnego_send(
}
state->gensec_status = status;
+ if (state->session_bind) {
+ in_flags |= SMB2_SESSION_FLAG_BINDING;
+ }
+
subreq = smb2cli_session_setup_send(state, state->ev,
session->transport->conn,
timeout_msec,
session->smbXcli,
- 0, /* in_flags */
+ in_flags,
0, /* in_capabilities */
0, /* in_channel */
state->previous_session_id,
@@ -191,6 +240,7 @@ static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
NTSTATUS status;
struct iovec *recv_iov;
uint32_t timeout_msec;
+ uint8_t in_flags = 0;
timeout_msec = session->transport->options.request_timeout * 1000;
@@ -246,22 +296,35 @@ static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
return;
}
- status = smb2cli_session_set_session_key(session->smbXcli,
- session_key,
- recv_iov);
- if (tevent_req_nterror(req, status)) {
- return;
+ if (state->session_bind) {
+ status = smb2cli_session_set_channel_key(session->smbXcli,
+ session_key,
+ recv_iov);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ session->needs_bind = false;
+ } else {
+ status = smb2cli_session_set_session_key(session->smbXcli,
+ session_key,
+ recv_iov);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
}
-
tevent_req_done(req);
return;
}
+ if (state->session_bind) {
+ in_flags |= SMB2_SESSION_FLAG_BINDING;
+ }
+
subreq = smb2cli_session_setup_send(state, state->ev,
session->transport->conn,
timeout_msec,
session->smbXcli,
- 0, /* in_flags */
+ in_flags,
0, /* in_capabilities */
0, /* in_channel */
state->previous_session_id,
diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h
index 101ef73807..73e117a961 100644
--- a/source4/libcli/smb2/smb2.h
+++ b/source4/libcli/smb2/smb2.h
@@ -116,6 +116,7 @@ struct smb2_session {
struct smb2_transport *transport;
struct gensec_security *gensec;
struct smbXcli_session *smbXcli;
+ bool needs_bind;
};