[Patches] libsmb make more usage of cli_credentials

Stefan Metzmacher metze at samba.org
Mon Dec 19 23:05:33 UTC 2016


Hi,

here're some patches which make use of the new
get_cmdline_auth_info_creds() and
change the SMB1 encryption to use cli_credentials.

Please review and push:-)

This depends on the "auth/credentials for user_auth_info"
patchset.

Everything is part of my master3-libsmb-ok branch, see
https://git.samba.org/?p=metze/samba/wip.git;a=shortlog;h=refs/heads/master3-libsmb-ok

Thanks!
metze
-------------- next part --------------
From 168863be1243f5813ab810c18f13863832789e80 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 31 Oct 2016 23:02:27 +0100
Subject: [PATCH 01/15] s3:libsmb: add cli_smb1_setup_encryption*() functions

This will allow us to setup SMB1 encryption by just passing
cli_credentials.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/cliconnect.c | 433 ++++++++++++++++++++++++++++++++++++++++++++
 source3/libsmb/proto.h      |   2 +
 2 files changed, 435 insertions(+)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 02c465c..4116bae 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -37,6 +37,7 @@
 #include "libsmb/nmblib.h"
 #include "librpc/ndr/libndr.h"
 #include "../libcli/smb/smbXcli_base.h"
+#include "../libcli/smb/smb_seal.h"
 #include "lib/param/param.h"
 
 #define STAR_SMBSERVER "*SMBSERVER"
@@ -2864,6 +2865,438 @@ fail:
 	return status;
 }
 
+struct cli_smb1_setup_encryption_blob_state {
+	uint16_t setup[1];
+	uint8_t param[4];
+	NTSTATUS status;
+	DATA_BLOB out;
+	uint16_t enc_ctx_id;
+};
+
+static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_smb1_setup_encryption_blob_send(TALLOC_CTX *mem_ctx,
+							struct tevent_context *ev,
+							struct cli_state *cli,
+							const DATA_BLOB in)
+{
+	struct tevent_req *req = NULL;
+	struct cli_smb1_setup_encryption_blob_state *state = NULL;
+	struct tevent_req *subreq = NULL;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_smb1_setup_encryption_blob_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	if (in.length > CLI_BUFFER_SIZE) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+		return tevent_req_post(req, ev);
+	}
+
+	SSVAL(state->setup+0,  0, TRANSACT2_SETFSINFO);
+	SSVAL(state->param, 0, 0);
+	SSVAL(state->param, 2, SMB_REQUEST_TRANSPORT_ENCRYPTION);
+
+	subreq = smb1cli_trans_send(state, ev, cli->conn,
+				    SMBtrans2,
+				    0, 0, /* _flags */
+				    0, 0, /* _flags2 */
+				    cli->timeout,
+				    cli->smb1.pid,
+				    cli->smb1.tcon,
+				    cli->smb1.session,
+				    NULL, /* pipe_name */
+				    0, /* fid */
+				    0, /* function */
+				    0, /* flags */
+				    state->setup, 1, 0,
+				    state->param, 4, 2,
+				    in.data, in.length, CLI_BUFFER_SIZE);
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq,
+				cli_smb1_setup_encryption_blob_done,
+				req);
+
+	return req;
+}
+
+static void cli_smb1_setup_encryption_blob_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+				struct tevent_req);
+	struct cli_smb1_setup_encryption_blob_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_blob_state);
+	uint8_t *rparam=NULL, *rdata=NULL;
+	uint32_t num_rparam, num_rdata;
+	NTSTATUS status;
+
+	status = smb1cli_trans_recv(subreq, state,
+				    NULL, /* recv_flags */
+				    NULL, 0, NULL, /* rsetup */
+				    &rparam, 0, &num_rparam,
+				    &rdata, 0, &num_rdata);
+	TALLOC_FREE(subreq);
+	state->status = status;
+	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+		status = NT_STATUS_OK;
+	}
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	if (num_rparam == 2) {
+		state->enc_ctx_id = SVAL(rparam, 0);
+	}
+	TALLOC_FREE(rparam);
+
+	state->out = data_blob_const(rdata, num_rdata);
+
+	tevent_req_done(req);
+}
+
+static NTSTATUS cli_smb1_setup_encryption_blob_recv(struct tevent_req *req,
+						    TALLOC_CTX *mem_ctx,
+						    DATA_BLOB *out,
+						    uint16_t *enc_ctx_id)
+{
+	struct cli_smb1_setup_encryption_blob_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_blob_state);
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		tevent_req_received(req);
+		return status;
+	}
+
+	status = state->status;
+
+	*out = state->out;
+	talloc_steal(mem_ctx, out->data);
+
+	*enc_ctx_id = state->enc_ctx_id;
+
+	tevent_req_received(req);
+	return status;
+}
+
+struct cli_smb1_setup_encryption_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+	struct smb_trans_enc_state *es;
+	DATA_BLOB blob_in;
+	DATA_BLOB blob_out;
+	bool local_ready;
+	bool remote_ready;
+};
+
+static void cli_smb1_setup_encryption_local_next(struct tevent_req *req);
+static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq);
+static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req);
+static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq);
+static void cli_smb1_setup_encryption_ready(struct tevent_req *req);
+
+static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
+						struct tevent_context *ev,
+						struct cli_state *cli,
+						struct cli_credentials *creds)
+{
+	struct tevent_req *req = NULL;
+	struct cli_smb1_setup_encryption_state *state = NULL;
+	struct auth_generic_state *ags = NULL;
+	const DATA_BLOB *b = NULL;
+	bool auth_requested = false;
+	enum credentials_use_kerberos krb5_state;
+	const char *mech_oid = NULL;
+	const char *target_service = NULL;
+	const char *target_hostname = NULL;
+	NTSTATUS status;
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct cli_smb1_setup_encryption_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+	state->cli = cli;
+
+	auth_requested = cli_credentials_authentication_requested(creds);
+	if (!auth_requested) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+		return tevent_req_post(req, ev);
+	}
+
+	target_service = "cifs";
+	target_hostname = smbXcli_conn_remote_name(cli->conn);
+
+	krb5_state = cli_credentials_get_kerberos_state(creds);
+	if (krb5_state == CRED_MUST_USE_KERBEROS) {
+		mech_oid = GENSEC_OID_SPNEGO;
+
+		b = smbXcli_conn_server_gss_blob(state->cli->conn);
+		if (b != NULL) {
+			state->blob_in = *b;
+		}
+
+		status = cli_session_creds_prepare_krb5(cli, creds);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+	} else {
+		/*
+		 * Be compatible with the <= 4.5 client code,
+		 * which used raw NTLMSSP unless kerberos
+		 * was forced.
+		 *
+		 * We need to check with the oldest server implementation
+		 * if we can remove this and always use
+		 * GENSEC_OID_SPNEGO.
+		 */
+		mech_oid = GENSEC_OID_NTLMSSP;
+	}
+
+	state->es = talloc_zero(state, struct smb_trans_enc_state);
+	if (tevent_req_nomem(state->es, req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	status = auth_generic_client_prepare(state->es, &ags);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	gensec_want_feature(ags->gensec_security,
+			    GENSEC_FEATURE_SIGN);
+	gensec_want_feature(ags->gensec_security,
+			    GENSEC_FEATURE_SEAL);
+
+	status = auth_generic_set_creds(ags, creds);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	if (target_service != NULL) {
+		status = gensec_set_target_service(ags->gensec_security,
+						   target_service);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+	}
+
+	if (target_hostname != NULL) {
+		status = gensec_set_target_hostname(ags->gensec_security,
+						    target_hostname);
+		if (tevent_req_nterror(req, status)) {
+			return tevent_req_post(req, ev);
+		}
+	}
+
+	gensec_set_max_update_size(ags->gensec_security,
+				   CLI_BUFFER_SIZE);
+
+	status = auth_generic_client_start(ags, mech_oid);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
+	}
+
+	/*
+	 * We only need the gensec_security part from here.
+	 */
+	state->es->gensec_security = talloc_move(state->es,
+						 &ags->gensec_security);
+	TALLOC_FREE(ags);
+
+	cli_smb1_setup_encryption_local_next(req);
+	if (!tevent_req_is_in_progress(req)) {
+		return tevent_req_post(req, ev);
+	}
+
+	return req;
+}
+
+static void cli_smb1_setup_encryption_local_next(struct tevent_req *req)
+{
+	struct cli_smb1_setup_encryption_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_state);
+	struct tevent_req *subreq = NULL;
+
+	if (state->local_ready) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	subreq = gensec_update_send(state, state->ev,
+			state->es->gensec_security,
+			state->blob_in);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, cli_smb1_setup_encryption_local_done, req);
+}
+
+static void cli_smb1_setup_encryption_local_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct cli_smb1_setup_encryption_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_state);
+	NTSTATUS status;
+
+	status = gensec_update_recv(subreq, state, &state->blob_out);
+	TALLOC_FREE(subreq);
+	state->blob_in = data_blob_null;
+	if (!NT_STATUS_IS_OK(status) &&
+	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
+	{
+		tevent_req_nterror(req, status);
+		return;
+	}
+
+	if (NT_STATUS_IS_OK(status)) {
+		state->local_ready = true;
+	}
+
+	/*
+	 * We always get NT_STATUS_OK from the server even if it is not ready.
+	 * So guess the server is ready when we are ready and already sent
+	 * our last blob to the server.
+	 */
+	if (state->local_ready && state->blob_out.length == 0) {
+		state->remote_ready = true;
+	}
+
+	if (state->local_ready && state->remote_ready) {
+		cli_smb1_setup_encryption_ready(req);
+		return;
+	}
+
+	cli_smb1_setup_encryption_remote_next(req);
+}
+
+static void cli_smb1_setup_encryption_remote_next(struct tevent_req *req)
+{
+	struct cli_smb1_setup_encryption_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_state);
+	struct tevent_req *subreq = NULL;
+
+	if (state->remote_ready) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	subreq = cli_smb1_setup_encryption_blob_send(state, state->ev,
+						     state->cli, state->blob_out);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq,
+				cli_smb1_setup_encryption_remote_done,
+				req);
+}
+
+static void cli_smb1_setup_encryption_remote_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req =
+		tevent_req_callback_data(subreq,
+		struct tevent_req);
+	struct cli_smb1_setup_encryption_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_state);
+	NTSTATUS status;
+
+	status = cli_smb1_setup_encryption_blob_recv(subreq, state,
+						     &state->blob_in,
+						     &state->es->enc_ctx_num);
+	TALLOC_FREE(subreq);
+	data_blob_free(&state->blob_out);
+	if (!NT_STATUS_IS_OK(status) &&
+	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED))
+	{
+		tevent_req_nterror(req, status);
+		return;
+	}
+
+	/*
+	 * We always get NT_STATUS_OK even if the server is not ready.
+	 * So guess the server is ready when we are ready and sent
+	 * our last blob to the server.
+	 */
+	if (state->local_ready) {
+		state->remote_ready = true;
+	}
+
+	if (state->local_ready && state->remote_ready) {
+		cli_smb1_setup_encryption_ready(req);
+		return;
+	}
+
+	cli_smb1_setup_encryption_local_next(req);
+}
+
+static void cli_smb1_setup_encryption_ready(struct tevent_req *req)
+{
+	struct cli_smb1_setup_encryption_state *state =
+		tevent_req_data(req,
+		struct cli_smb1_setup_encryption_state);
+	struct smb_trans_enc_state *es = NULL;
+
+	if (state->blob_in.length != 0) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	if (state->blob_out.length != 0) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	es = talloc_move(state->cli->conn, &state->es);
+	es->enc_on = true;
+	smb1cli_conn_set_encryption(state->cli->conn, es);
+	es = NULL;
+
+	tevent_req_done(req);
+}
+
+static NTSTATUS cli_smb1_setup_encryption_recv(struct tevent_req *req)
+{
+	return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
+				   struct cli_credentials *creds)
+{
+	struct tevent_context *ev = NULL;
+	struct tevent_req *req = NULL;
+	NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+	ev = samba_tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		goto fail;
+	}
+	req = cli_smb1_setup_encryption_send(ev, ev, cli, creds);
+	if (req == NULL) {
+		goto fail;
+	}
+	if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+		goto fail;
+	}
+	status = cli_smb1_setup_encryption_recv(req);
+ fail:
+	TALLOC_FREE(ev);
+	return status;
+}
+
 /**
    establishes a connection right up to doing tconX, password specified.
    @param output_cli A fully initialised cli structure, non-null only on success
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 290183c..8e25590 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -94,6 +94,8 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
 			      const char *dest_host,
 			      const struct sockaddr_storage *dest_ss, int port,
 			      int signing_state, int flags);
+NTSTATUS cli_smb1_setup_encryption(struct cli_state *cli,
+				   struct cli_credentials *creds);
 struct tevent_req *cli_full_connection_creds_send(
 	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 	const char *my_name, const char *dest_host,
-- 
1.9.1


From 21cdfb6664fbcc06afe3f345972f1ee5a97acbd6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 3 Nov 2016 14:50:28 +0100
Subject: [PATCH 02/15] s3:torture: make use of cli_smb1_setup_encryption() in
 force_cli_encryption()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/torture/torture.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 7072f3c..1a57f41 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -108,15 +108,7 @@ static bool force_cli_encryption(struct cli_state *c,
 		return false;
 	}
 
-	if (c->use_kerberos) {
-		status = cli_gss_smb_encryption_start(c);
-	} else {
-		status = cli_raw_ntlm_smb_encryption_start(c,
-						username,
-						password,
-						workgroup);
-	}
-
+	status = cli_smb1_setup_encryption(c, torture_creds);
 	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("Encryption required and "
 			"setup failed with error %s.\n",
-- 
1.9.1


From a940762a614ddbb0a1f6351cc1183f28b240195a Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 3 Nov 2016 14:50:28 +0100
Subject: [PATCH 03/15] s3:client: make use of cli_smb1_setup_encryption() in
 cmd_posix_encrypt()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/client/client.c | 45 +++++++++++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 14 deletions(-)

diff --git a/source3/client/client.c b/source3/client/client.c
index cde9776..14d0ed7 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -2535,35 +2535,52 @@ static int cmd_posix_encrypt(void)
 {
 	TALLOC_CTX *ctx = talloc_tos();
 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+	char *domain = NULL;
+	char *user = NULL;
+	char *password = NULL;
+	struct cli_credentials *creds = NULL;
+	struct cli_credentials *lcreds = NULL;
 
-	if (cli->use_kerberos) {
-		status = cli_gss_smb_encryption_start(cli);
-	} else {
-		char *domain = NULL;
-		char *user = NULL;
-		char *password = NULL;
+	if (next_token_talloc(ctx, &cmd_ptr, &domain, NULL)) {
 
-		if (!next_token_talloc(ctx, &cmd_ptr,&domain,NULL)) {
+		if (!next_token_talloc(ctx, &cmd_ptr, &user, NULL)) {
 			d_printf("posix_encrypt domain user password\n");
 			return 1;
 		}
 
-		if (!next_token_talloc(ctx, &cmd_ptr,&user,NULL)) {
+		if (!next_token_talloc(ctx, &cmd_ptr, &password, NULL)) {
 			d_printf("posix_encrypt domain user password\n");
 			return 1;
 		}
 
-		if (!next_token_talloc(ctx, &cmd_ptr,&password,NULL)) {
+		lcreds = cli_session_creds_init(ctx,
+						user,
+						domain,
+						NULL, /* realm */
+						password,
+						false, /* use_kerberos */
+						false, /* fallback_after_kerberos */
+						false, /* use_ccache */
+						false); /* password_is_nt_hash */
+		if (lcreds == NULL) {
+			d_printf("cli_session_creds_init() failed.\n");
+			return -1;
+		}
+		creds = lcreds;
+	} else {
+		bool auth_requested = false;
+
+		creds = get_cmdline_auth_info_creds(auth_info);
+
+		auth_requested = cli_credentials_authentication_requested(creds);
+		if (!auth_requested) {
 			d_printf("posix_encrypt domain user password\n");
 			return 1;
 		}
-
-		status = cli_raw_ntlm_smb_encryption_start(cli,
-							user,
-							password,
-							domain);
 	}
 
+	status = cli_smb1_setup_encryption(cli, creds);
+	talloc_unlink(ctx, lcreds);
 	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
 	} else {
-- 
1.9.1


From 3b470464f3c8caba4c29b6b8363cc2ce52e98cca Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 3 Nov 2016 14:50:28 +0100
Subject: [PATCH 04/15] s3:libsmb: make use of cli_smb1_setup_encryption() in
 cli_cm_force_encryption()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clidfs.c | 45 +++++++++++++++++++++++++++++++++++----------
 1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index b44bbef..bf40ee4 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -48,7 +48,10 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
 			const char *domain,
 			const char *sharename)
 {
+	uint16_t major, minor;
+	uint32_t caplow, caphigh;
 	NTSTATUS status;
+	struct cli_credentials *creds = NULL;
 
 	if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
 		status = smb2cli_session_encryption_on(c->smb2.session);
@@ -64,30 +67,52 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
 		return status;
 	}
 
-	status = cli_force_encryption(c,
-					username,
-					password,
-					domain);
-
-	if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED)) {
+	if (!SERVER_HAS_UNIX_CIFS(c)) {
 		d_printf("Encryption required and "
 			"server that doesn't support "
 			"UNIX extensions - failing connect\n");
-	} else if (NT_STATUS_EQUAL(status,NT_STATUS_UNKNOWN_REVISION)) {
+		return NT_STATUS_NOT_SUPPORTED;
+	}
+
+	status = cli_unix_extensions_version(c, &major, &minor, &caplow,
+					     &caphigh);
+	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("Encryption required and "
 			"can't get UNIX CIFS extensions "
 			"version from server.\n");
-	} else if (NT_STATUS_EQUAL(status,NT_STATUS_UNSUPPORTED_COMPRESSION)) {
+		return NT_STATUS_UNKNOWN_REVISION;
+	}
+
+	if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
 		d_printf("Encryption required and "
 			"share %s doesn't support "
 			"encryption.\n", sharename);
-	} else if (!NT_STATUS_IS_OK(status)) {
+		return NT_STATUS_UNSUPPORTED_COMPRESSION;
+	}
+
+	creds = cli_session_creds_init(c,
+				       username,
+				       domain,
+				       NULL, /* default realm */
+				       password,
+				       c->use_kerberos,
+				       c->fallback_after_kerberos,
+				       c->use_ccache,
+				       c->pw_nt_hash);
+	if (creds == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = cli_smb1_setup_encryption(c, creds);
+	talloc_unlink(c, creds);
+	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("Encryption required and "
 			"setup failed with error %s.\n",
 			nt_errstr(status));
+		return status;
 	}
 
-	return status;
+	return NT_STATUS_OK;
 }
 
 /********************************************************************
-- 
1.9.1


From 356a4695ebc088a18249f546a94c91ed9ba5ac06 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 3 Nov 2016 14:50:28 +0100
Subject: [PATCH 05/15] s3:libsmb: remove unused cli_*_encryption* functions

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clifsinfo.c | 245 ---------------------------------------------
 source3/libsmb/proto.h     |   9 --
 2 files changed, 254 deletions(-)

diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index ca4dc38..119b121 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -23,7 +23,6 @@
 #include "libsmb/libsmb.h"
 #include "../lib/util/tevent_ntstatus.h"
 #include "async_smb.h"
-#include "../libcli/smb/smb_seal.h"
 #include "trans2.h"
 #include "auth_generic.h"
 #include "auth/gensec/gensec.h"
@@ -535,250 +534,6 @@ NTSTATUS cli_get_posix_fs_info(struct cli_state *cli,
 	return NT_STATUS_OK;
 }
 
-
-/******************************************************************************
- Send/receive the request encryption blob.
-******************************************************************************/
-
-static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out)
-{
-	uint16_t setup[1];
-	uint8_t param[4];
-	uint8_t *rparam=NULL, *rdata=NULL;
-	uint32_t num_rparam, num_rdata;
-	NTSTATUS status;
-
-	SSVAL(setup+0, 0, TRANSACT2_SETFSINFO);
-	SSVAL(param,0,0);
-	SSVAL(param,2,SMB_REQUEST_TRANSPORT_ENCRYPTION);
-
-	status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0,
-			   setup, 1, 0,
-			   param, 4, 2,
-			   (uint8_t *)in->data, in->length, CLI_BUFFER_SIZE,
-			   NULL,	  /* recv_flags */
-			   NULL, 0, NULL, /* rsetup */
-			   &rparam, 0, &num_rparam,
-			   &rdata, 0, &num_rdata);
-
-	if (!NT_STATUS_IS_OK(status) &&
-	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-		return status;
-	}
-
-	*out = data_blob(rdata, num_rdata);
-	*param_out = data_blob(rparam, num_rparam);
-
-	TALLOC_FREE(rparam);
-	TALLOC_FREE(rdata);
-	return status;
-}
-
-/******************************************************************************
- Start a raw ntlmssp encryption.
-******************************************************************************/
-
-NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, 
-				const char *user,
-				const char *pass,
-				const char *domain)
-{
-	DATA_BLOB blob_in = data_blob_null;
-	DATA_BLOB blob_out = data_blob_null;
-	DATA_BLOB param_out = data_blob_null;
-	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-	struct auth_generic_state *auth_generic_state;
-	struct smb_trans_enc_state *es = talloc_zero(NULL, struct smb_trans_enc_state);
-	if (!es) {
-		return NT_STATUS_NO_MEMORY;
-	}
-	status = auth_generic_client_prepare(es,
-					     &auth_generic_state);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
-	gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SESSION_KEY);
-	gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
-
-	if (!NT_STATUS_IS_OK(status = auth_generic_set_username(auth_generic_state, user))) {
-		goto fail;
-	}
-	if (!NT_STATUS_IS_OK(status = auth_generic_set_domain(auth_generic_state, domain))) {
-		goto fail;
-	}
-	if (!NT_STATUS_IS_OK(status = auth_generic_set_password(auth_generic_state, pass))) {
-		goto fail;
-	}
-
-	if (!NT_STATUS_IS_OK(status = auth_generic_client_start(auth_generic_state, GENSEC_OID_NTLMSSP))) {
-		goto fail;
-	}
-
-	do {
-		status = gensec_update(auth_generic_state->gensec_security, auth_generic_state,
-				       blob_in, &blob_out);
-		data_blob_free(&blob_in);
-		data_blob_free(&param_out);
-		if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) {
-			NTSTATUS trans_status = enc_blob_send_receive(cli,
-									&blob_out,
-									&blob_in,
-									&param_out);
-			if (!NT_STATUS_EQUAL(trans_status,
-					NT_STATUS_MORE_PROCESSING_REQUIRED) &&
-					!NT_STATUS_IS_OK(trans_status)) {
-				status = trans_status;
-			} else {
-				if (param_out.length == 2) {
-					es->enc_ctx_num = SVAL(param_out.data, 0);
-				}
-			}
-		}
-		data_blob_free(&blob_out);
-	} while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
-
-	data_blob_free(&blob_in);
-
-	if (NT_STATUS_IS_OK(status)) {
-		es->enc_on = true;
-		/*
-		 * Replace the old state, if any.
-		 * We only need the gensec_security part from here.
-		 */
-		es->gensec_security = talloc_move(es,
-						  &auth_generic_state->gensec_security);
-		smb1cli_conn_set_encryption(cli->conn, es);
-		es = NULL;
-	}
-
-  fail:
-	TALLOC_FREE(es);
-	return status;
-}
-
-/******************************************************************************
- Start a SPNEGO gssapi encryption context.
-******************************************************************************/
-
-NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
-{
-	DATA_BLOB blob_recv = data_blob_null;
-	DATA_BLOB blob_send = data_blob_null;
-	DATA_BLOB param_out = data_blob_null;
-	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-	struct auth_generic_state *auth_generic_state;
-	struct smb_trans_enc_state *es = talloc_zero(NULL, struct smb_trans_enc_state);
-
-	if (!es) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	status = auth_generic_client_prepare(es,
-					     &auth_generic_state);
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
-	gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SESSION_KEY);
-	gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
-
-	cli_credentials_set_kerberos_state(auth_generic_state->credentials, 
-					   CRED_MUST_USE_KERBEROS);
-
-	status = gensec_set_target_service(auth_generic_state->gensec_security, "cifs");
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
-	status = gensec_set_target_hostname(auth_generic_state->gensec_security, 
-					    smbXcli_conn_remote_name(cli->conn));
-	if (!NT_STATUS_IS_OK(status)) {
-		goto fail;
-	}
-
-	if (!NT_STATUS_IS_OK(status = auth_generic_client_start(auth_generic_state, GENSEC_OID_SPNEGO))) {
-		goto fail;
-	}
-
-	status = gensec_update(auth_generic_state->gensec_security, talloc_tos(),
-			       blob_recv, &blob_send);
-
-	do {
-		data_blob_free(&blob_recv);
-		status = enc_blob_send_receive(cli, &blob_send, &blob_recv, &param_out);
-		if (param_out.length == 2) {
-			es->enc_ctx_num = SVAL(param_out.data, 0);
-		}
-		data_blob_free(&blob_send);
-		status = gensec_update(auth_generic_state->gensec_security, talloc_tos(),
-				       blob_recv, &blob_send);
-	} while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
-	data_blob_free(&blob_recv);
-
-	if (NT_STATUS_IS_OK(status)) {
-		if (!gensec_have_feature(auth_generic_state->gensec_security, 
-					 GENSEC_FEATURE_SIGN) ||
-		    !gensec_have_feature(auth_generic_state->gensec_security, 
-					 GENSEC_FEATURE_SEAL)) {
-			status = NT_STATUS_ACCESS_DENIED;
-		}
-	}
-
-	if (NT_STATUS_IS_OK(status)) {
-		es->enc_on = true;
-		/*
-		 * Replace the old state, if any.
-		 * We only need the gensec_security part from here.
-		 */
-		es->gensec_security = talloc_move(es,
-						  &auth_generic_state->gensec_security);
-		smb1cli_conn_set_encryption(cli->conn, es);
-		es = NULL;
-	}
-fail:
-	TALLOC_FREE(es);
-	return status;
-}
-
-/********************************************************************
- Ensure a connection is encrypted.
-********************************************************************/
-
-NTSTATUS cli_force_encryption(struct cli_state *c,
-			const char *username,
-			const char *password,
-			const char *domain)
-{
-	uint16_t major, minor;
-	uint32_t caplow, caphigh;
-	NTSTATUS status;
-
-	if (!SERVER_HAS_UNIX_CIFS(c)) {
-		return NT_STATUS_NOT_SUPPORTED;
-	}
-
-	status = cli_unix_extensions_version(c, &major, &minor, &caplow,
-					     &caphigh);
-	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(10, ("cli_force_encryption: cli_unix_extensions_version "
-			   "returned %s\n", nt_errstr(status)));
-		return NT_STATUS_UNKNOWN_REVISION;
-	}
-
-	if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
-		return NT_STATUS_UNSUPPORTED_COMPRESSION;
-	}
-
-	if (c->use_kerberos) {
-		return cli_gss_smb_encryption_start(c);
-	}
-	return cli_raw_ntlm_smb_encryption_start(c,
-					username,
-					password,
-					domain);
-}
-
 /****************************************************************************
  Do a UNIX extensions SMB_QUERY_POSIX_WHOAMI call.
 ****************************************************************************/
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 8e25590..b774a67 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -688,15 +688,6 @@ NTSTATUS cli_get_posix_fs_info(struct cli_state *cli,
 			       uint64_t *total_file_nodes,
 			       uint64_t *free_file_nodes,
 			       uint64_t *fs_identifier);
-NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli,
-				const char *user,
-				const char *pass,
-				const char *domain);
-NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli);
-NTSTATUS cli_force_encryption(struct cli_state *c,
-			const char *username,
-			const char *password,
-			const char *domain);
 struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx,
 			struct tevent_context *ev,
 			struct cli_state *cli);
-- 
1.9.1


From 616dba57f8c005113b3151918be6babda30232f9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sun, 30 Oct 2016 16:45:39 +0100
Subject: [PATCH 06/15] s3:libsmb: make use of get_cmdline_auth_info_creds() in
 clidfs.c:do_connect()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clidfs.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index bf40ee4..ec0e7f8 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -140,6 +140,7 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
 	NTSTATUS status;
 	int flags = 0;
 	int signing_state = get_cmdline_auth_info_signing_state(auth_info);
+	struct cli_credentials *creds = NULL;
 
 	if (force_encrypt) {
 		signing_state = SMB_SIGNING_REQUIRED;
@@ -220,9 +221,9 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
 		domain = lp_workgroup();
 	}
 
-	status = cli_session_setup(c, username,
-				   password,
-				   domain);
+	creds = get_cmdline_auth_info_creds(auth_info);
+
+	status = cli_session_setup_creds(c, creds);
 	if (!NT_STATUS_IS_OK(status)) {
 		/* If a password was not supplied then
 		 * try again with a null username. */
-- 
1.9.1


From 7c572832eb847a654173004bdea6c308e93301a3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sun, 30 Oct 2016 16:42:45 +0100
Subject: [PATCH 07/15] s3:libsmb: avoid using cli_session_setup() in
 SMBC_server_internal()

Using cli_session_creds_init() will allow it to be passed to other sub functions
later.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/libsmb_server.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index e0cdc97..4ea0550 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -281,6 +281,11 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 	int flags = 0;
 	struct smbXcli_tcon *tcon = NULL;
 	int signing_state = SMB_SIGNING_DEFAULT;
+	struct cli_credentials *creds = NULL;
+	bool use_kerberos = false;
+	bool fallback_after_kerberos = false;
+	bool use_ccache = false;
+	bool pw_nt_hash = false;
 
 	ZERO_STRUCT(c);
 	*in_cache = false;
@@ -432,18 +437,22 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 
 	if (smbc_getOptionUseKerberos(context)) {
 		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
+		use_kerberos = true;
 	}
 
 	if (smbc_getOptionFallbackAfterKerberos(context)) {
 		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
+		fallback_after_kerberos = true;
 	}
 
 	if (smbc_getOptionUseCCache(context)) {
 		flags |= CLI_FULL_CONNECTION_USE_CCACHE;
+		use_ccache = true;
 	}
 
 	if (smbc_getOptionUseNTHash(context)) {
 		flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
+		pw_nt_hash = true;
 	}
 
 	if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
@@ -494,18 +503,30 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 	username_used = *pp_username;
 	password_used = *pp_password;
 
-	if (!NT_STATUS_IS_OK(cli_session_setup(c, username_used,
-					       password_used,
-					       *pp_workgroup))) {
+	creds = cli_session_creds_init(c,
+				       username_used,
+				       *pp_workgroup,
+				       NULL, /* realm */
+				       password_used,
+				       use_kerberos,
+				       fallback_after_kerberos,
+				       use_ccache,
+				       pw_nt_hash);
+	if (creds == NULL) {
+		cli_shutdown(c);
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	status = cli_session_setup_creds(c, creds);
+	if (!NT_STATUS_IS_OK(status)) {
 
                 /* Failed.  Try an anonymous login, if allowed by flags. */
 		username_used = "";
 		password_used = "";
 
                 if (smbc_getOptionNoAutoAnonymousLogin(context) ||
-		    !NT_STATUS_IS_OK(cli_session_setup(c, username_used,
-						       password_used,
-                                                       *pp_workgroup))) {
+		    !NT_STATUS_IS_OK(cli_session_setup_anon(c))) {
 
                         cli_shutdown(c);
                         errno = EPERM;
-- 
1.9.1


From 9aa2e67bdb05bcc4ed2cae241b4cc5288b8fb571 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Sun, 30 Oct 2016 16:46:54 +0100
Subject: [PATCH 08/15] s3:libsmb: remove now unused cli_session_setup()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/cliconnect.c | 37 -------------------------------------
 source3/libsmb/proto.h      |  4 ----
 2 files changed, 41 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4116bae..f5f399a 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -1775,43 +1775,6 @@ NTSTATUS cli_session_setup_anon(struct cli_state *cli)
 	return NT_STATUS_OK;
 }
 
-NTSTATUS cli_session_setup(struct cli_state *cli,
-			   const char *user,
-			   const char *pass,
-			   const char *workgroup)
-{
-	NTSTATUS status = NT_STATUS_NO_MEMORY;
-	const char *dest_realm = NULL;
-	struct cli_credentials *creds = NULL;
-
-	/*
-	 * dest_realm is only valid in the winbindd use case,
-	 * where we also have the account in that realm.
-	 */
-	dest_realm = cli_state_remote_realm(cli);
-
-	creds = cli_session_creds_init(cli,
-				       user,
-				       workgroup,
-				       dest_realm,
-				       pass,
-				       cli->use_kerberos,
-				       cli->fallback_after_kerberos,
-				       cli->use_ccache,
-				       cli->pw_nt_hash);
-	if (creds == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	status = cli_session_setup_creds(cli, creds);
-	TALLOC_FREE(creds);
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
-	}
-
-	return NT_STATUS_OK;
-}
-
 /****************************************************************************
  Send a uloggoff.
 *****************************************************************************/
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index b774a67..aee3771 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -53,10 +53,6 @@ NTSTATUS cli_session_setup_creds_recv(struct tevent_req *req);
 NTSTATUS cli_session_setup_creds(struct cli_state *cli,
 				 struct cli_credentials *creds);
 NTSTATUS cli_session_setup_anon(struct cli_state *cli);
-NTSTATUS cli_session_setup(struct cli_state *cli,
-			   const char *user,
-			   const char *pass,
-			   const char *workgroup);
 struct tevent_req *cli_session_setup_guest_create(TALLOC_CTX *mem_ctx,
 						  struct tevent_context *ev,
 						  struct cli_state *cli,
-- 
1.9.1


From ab0a5172f37dc58585c6c2c70b5d987987696475 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 9 Dec 2016 09:06:38 +0100
Subject: [PATCH 09/15] s3:libsmb: make use of cli_tree_connect_creds() in
 clidfs.c:do_connect()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clidfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index ec0e7f8..48b8efd 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -280,7 +280,7 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
 
 	/* must be a normal share */
 
-	status = cli_tree_connect(c, sharename, "?????", password);
+	status = cli_tree_connect_creds(c, sharename, "?????", creds);
 	if (!NT_STATUS_IS_OK(status)) {
 		d_printf("tree connect failed: %s\n", nt_errstr(status));
 		cli_shutdown(c);
-- 
1.9.1


From f1af8dd486857c400f0b5810bc66eef7eb3afec1 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Mon, 12 Dec 2016 06:00:32 +0100
Subject: [PATCH 10/15] s3:libsmb: make use of cli_tree_connect_creds() in
 SMBC_server_internal()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/libsmb_server.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index 4ea0550..3f206e3 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -562,7 +562,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 
 	/* must be a normal share */
 
-	status = cli_tree_connect(c, share, "?????", *pp_password);
+	status = cli_tree_connect_creds(c, share, "?????", creds);
 	if (!NT_STATUS_IS_OK(status)) {
 		errno = map_errno_from_nt_status(status);
 		cli_shutdown(c);
-- 
1.9.1


From 6f6723d8552bcc3d12aab77403f6a0cb24a00678 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 3 Nov 2016 17:26:41 +0100
Subject: [PATCH 11/15] s3:libsmb: split out cli_cm_force_encryption_creds()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clidfs.c | 40 +++++++++++++++++++++++++---------------
 source3/libsmb/proto.h  |  3 +++
 2 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 48b8efd..f22313d 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -42,16 +42,13 @@
  Ensure a connection is encrypted.
 ********************************************************************/
 
-NTSTATUS cli_cm_force_encryption(struct cli_state *c,
-			const char *username,
-			const char *password,
-			const char *domain,
-			const char *sharename)
+NTSTATUS cli_cm_force_encryption_creds(struct cli_state *c,
+				       struct cli_credentials *creds,
+				       const char *sharename)
 {
 	uint16_t major, minor;
 	uint32_t caplow, caphigh;
 	NTSTATUS status;
-	struct cli_credentials *creds = NULL;
 
 	if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
 		status = smb2cli_session_encryption_on(c->smb2.session);
@@ -90,6 +87,26 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
 		return NT_STATUS_UNSUPPORTED_COMPRESSION;
 	}
 
+	status = cli_smb1_setup_encryption(c, creds);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("Encryption required and "
+			"setup failed with error %s.\n",
+			nt_errstr(status));
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
+NTSTATUS cli_cm_force_encryption(struct cli_state *c,
+			const char *username,
+			const char *password,
+			const char *domain,
+			const char *sharename)
+{
+	struct cli_credentials *creds = NULL;
+	NTSTATUS status;
+
 	creds = cli_session_creds_init(c,
 				       username,
 				       domain,
@@ -103,16 +120,9 @@ NTSTATUS cli_cm_force_encryption(struct cli_state *c,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	status = cli_smb1_setup_encryption(c, creds);
+	status = cli_cm_force_encryption_creds(c, creds, sharename);
 	talloc_unlink(c, creds);
-	if (!NT_STATUS_IS_OK(status)) {
-		d_printf("Encryption required and "
-			"setup failed with error %s.\n",
-			nt_errstr(status));
-		return status;
-	}
-
-	return NT_STATUS_OK;
+	return status;
 }
 
 /********************************************************************
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index aee3771..62720fd 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -133,6 +133,9 @@ struct cli_state *get_ipc_connect_master_ip_bcast(TALLOC_CTX *ctx,
 
 /* The following definitions come from libsmb/clidfs.c  */
 
+NTSTATUS cli_cm_force_encryption_creds(struct cli_state *c,
+				       struct cli_credentials *creds,
+				       const char *sharename);
 NTSTATUS cli_cm_force_encryption(struct cli_state *c,
 			const char *username,
 			const char *password,
-- 
1.9.1


From 4a3d93c167d91197e66380f89211206cdb0a31fa Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 3 Nov 2016 17:27:49 +0100
Subject: [PATCH 12/15] s3:libsmb: make use of cli_cm_force_encryption_creds()
 where we already have creds

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clidfs.c        | 8 +++-----
 source3/libsmb/libsmb_server.c | 8 +++-----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index f22313d..5f06d3b 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -298,11 +298,9 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
 	}
 
 	if (force_encrypt) {
-		status = cli_cm_force_encryption(c,
-					username,
-					password,
-					domain,
-					sharename);
+		status = cli_cm_force_encryption_creds(c,
+						       creds,
+						       sharename);
 		if (!NT_STATUS_IS_OK(status)) {
 			cli_shutdown(c);
 			return status;
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index 3f206e3..d737d25 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -609,11 +609,9 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 
 	if (context->internal->smb_encryption_level) {
 		/* Attempt encryption. */
-		status = cli_cm_force_encryption(c,
-						 username_used,
-						 password_used,
-						 *pp_workgroup,
-						 share);
+		status = cli_cm_force_encryption_creds(c,
+						       creds,
+						       share);
 		if (!NT_STATUS_IS_OK(status)) {
 
 			/*
-- 
1.9.1


From 90a82d3c390fe873f450c37b7008effba25ce792 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 4 Nov 2016 12:37:08 +0100
Subject: [PATCH 13/15] s3:client: use cli_cm_force_encryption_creds in
 smbspool.c (in a #if 0 section)

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/client/smbspool.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
index a447836..10e89c7 100644
--- a/source3/client/smbspool.c
+++ b/source3/client/smbspool.c
@@ -474,11 +474,7 @@ smb_complete_connection(const char *myname,
 #if 0
 	/* Need to work out how to specify this on the URL. */
 	if (smb_encrypt) {
-		if (!cli_cm_force_encryption(cli,
-					     username,
-					     password,
-					     workgroup,
-					     share)) {
+		if (!cli_cm_force_encryption_creds(cli, creds, share)) {
 			fprintf(stderr, "ERROR: encryption setup failed\n");
 			cli_shutdown(cli);
 			return NULL;
-- 
1.9.1


From 05df383cc0f2c6d0407f720be7134e1ead2b8977 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 4 Nov 2016 12:25:34 +0100
Subject: [PATCH 14/15] s3:libsmb: pass cli_credentials to
 cli_check_msdfs_proxy()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/clidfs.c        | 15 +++------------
 source3/libsmb/libsmb_server.c |  4 +---
 source3/libsmb/proto.h         |  4 +---
 3 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 5f06d3b..cb9ec26 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -277,10 +277,7 @@ static NTSTATUS do_connect(TALLOC_CTX *ctx,
 	if (smbXcli_conn_dfs_supported(c->conn) &&
 			cli_check_msdfs_proxy(ctx, c, sharename,
 				&newserver, &newshare,
-				force_encrypt,
-				username,
-				password,
-				domain)) {
+				force_encrypt, creds)) {
 		cli_shutdown(c);
 		return do_connect(ctx, newserver,
 				newshare, auth_info, false,
@@ -1200,9 +1197,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 				char **pp_newserver,
 				char **pp_newshare,
 				bool force_encrypt,
-				const char *username,
-				const char *password,
-				const char *domain)
+				struct cli_credentials *creds)
 {
 	struct client_dfs_referral *refs = NULL;
 	size_t num_refs = 0;
@@ -1241,11 +1236,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 	}
 
 	if (force_encrypt) {
-		status = cli_cm_force_encryption(cli,
-					username,
-					password,
-					domain,
-					"IPC$");
+		status = cli_cm_force_encryption_creds(cli, creds, "IPC$");
 		if (!NT_STATUS_IS_OK(status)) {
 			return false;
 		}
diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c
index d737d25..b0e5926 100644
--- a/source3/libsmb/libsmb_server.c
+++ b/source3/libsmb/libsmb_server.c
@@ -548,9 +548,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
 				   not support smbc_smb_encrypt_level type */
 				context->internal->smb_encryption_level ?
 					true : false,
-				*pp_username,
-				*pp_password,
-				*pp_workgroup)) {
+				creds)) {
 		cli_shutdown(c);
 		srv = SMBC_server_internal(ctx, context, connect_if_not_found,
 				newserver, port, newshare, pp_workgroup,
diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h
index 62720fd..764f3fc 100644
--- a/source3/libsmb/proto.h
+++ b/source3/libsmb/proto.h
@@ -174,9 +174,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
 			char **pp_newserver,
 			char **pp_newshare,
 			bool force_encrypt,
-			const char *username,
-			const char *password,
-			const char *domain);
+			struct cli_credentials *creds);
 
 /* The following definitions come from libsmb/clientgen.c  */
 
-- 
1.9.1


From 138a3b5583ee931cc601c5c2f104b2e5515fdbef Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Thu, 8 Dec 2016 12:25:22 +0100
Subject: [PATCH 15/15] s3:libsmb: always use GENSEC_OID_SPNEGO in
 cli_smb1_setup_encryption_send()

Also old servers should be able to handle NTLMSSP via SPNEGO.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 source3/libsmb/cliconnect.c | 36 +++++++++---------------------------
 1 file changed, 9 insertions(+), 27 deletions(-)

diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index f5f399a..55768bf 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2975,8 +2975,6 @@ static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
 	struct auth_generic_state *ags = NULL;
 	const DATA_BLOB *b = NULL;
 	bool auth_requested = false;
-	enum credentials_use_kerberos krb5_state;
-	const char *mech_oid = NULL;
 	const char *target_service = NULL;
 	const char *target_hostname = NULL;
 	NTSTATUS status;
@@ -2998,30 +2996,9 @@ static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
 	target_service = "cifs";
 	target_hostname = smbXcli_conn_remote_name(cli->conn);
 
-	krb5_state = cli_credentials_get_kerberos_state(creds);
-	if (krb5_state == CRED_MUST_USE_KERBEROS) {
-		mech_oid = GENSEC_OID_SPNEGO;
-
-		b = smbXcli_conn_server_gss_blob(state->cli->conn);
-		if (b != NULL) {
-			state->blob_in = *b;
-		}
-
-		status = cli_session_creds_prepare_krb5(cli, creds);
-		if (tevent_req_nterror(req, status)) {
-			return tevent_req_post(req, ev);
-		}
-	} else {
-		/*
-		 * Be compatible with the <= 4.5 client code,
-		 * which used raw NTLMSSP unless kerberos
-		 * was forced.
-		 *
-		 * We need to check with the oldest server implementation
-		 * if we can remove this and always use
-		 * GENSEC_OID_SPNEGO.
-		 */
-		mech_oid = GENSEC_OID_NTLMSSP;
+	status = cli_session_creds_prepare_krb5(cli, creds);
+	if (tevent_req_nterror(req, status)) {
+		return tevent_req_post(req, ev);
 	}
 
 	state->es = talloc_zero(state, struct smb_trans_enc_state);
@@ -3063,7 +3040,12 @@ static struct tevent_req *cli_smb1_setup_encryption_send(TALLOC_CTX *mem_ctx,
 	gensec_set_max_update_size(ags->gensec_security,
 				   CLI_BUFFER_SIZE);
 
-	status = auth_generic_client_start(ags, mech_oid);
+	b = smbXcli_conn_server_gss_blob(state->cli->conn);
+	if (b != NULL) {
+		state->blob_in = *b;
+	}
+
+	status = auth_generic_client_start(ags, GENSEC_OID_SPNEGO);
 	if (tevent_req_nterror(req, status)) {
 		return tevent_req_post(req, ev);
 	}
-- 
1.9.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20161220/3af4d672/signature.sig>


More information about the samba-technical mailing list