mirror of
https://github.com/samba-team/samba.git
synced 2025-10-18 19:33:16 +03:00
s3:libsmb: Add encryption support to cli_full_connection_creds*()
Pair-Programmed-With: Andreas Schneider <asn@samba.org> Signed-off-by: Andreas Schneider <asn@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
committed by
Andreas Schneider
parent
ba04151a01
commit
8a5bc0a6a1
@@ -3352,6 +3352,10 @@ static int cli_full_connection_creds_state_destructor(
|
||||
static void cli_full_connection_creds_conn_done(struct tevent_req *subreq);
|
||||
static void cli_full_connection_creds_sess_start(struct tevent_req *req);
|
||||
static void cli_full_connection_creds_sess_done(struct tevent_req *subreq);
|
||||
static void cli_full_connection_creds_enc_start(struct tevent_req *req);
|
||||
static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq);
|
||||
static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq);
|
||||
static void cli_full_connection_creds_enc_done(struct tevent_req *subreq);
|
||||
static void cli_full_connection_creds_tcon_start(struct tevent_req *req);
|
||||
static void cli_full_connection_creds_tcon_done(struct tevent_req *subreq);
|
||||
|
||||
@@ -3366,6 +3370,8 @@ struct tevent_req *cli_full_connection_creds_send(
|
||||
struct tevent_req *req, *subreq;
|
||||
struct cli_full_connection_creds_state *state;
|
||||
enum smb_signing_setting signing_state;
|
||||
enum smb_encryption_setting encryption_state =
|
||||
cli_credentials_get_smb_encryption(creds);
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct cli_full_connection_creds_state);
|
||||
@@ -3386,6 +3392,16 @@ struct tevent_req *cli_full_connection_creds_send(
|
||||
signing_state = cli_credentials_get_smb_signing(creds);
|
||||
}
|
||||
|
||||
if (encryption_state == SMB_ENCRYPTION_REQUIRED) {
|
||||
if (flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK) {
|
||||
encryption_state = SMB_ENCRYPTION_DESIRED;
|
||||
}
|
||||
}
|
||||
|
||||
if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
|
||||
signing_state = SMB_SIGNING_REQUIRED;
|
||||
}
|
||||
|
||||
subreq = cli_start_connection_send(
|
||||
state, ev, my_name, dest_host, dest_ss, port,
|
||||
signing_state, flags);
|
||||
@@ -3460,6 +3476,156 @@ static void cli_full_connection_creds_sess_done(struct tevent_req *subreq)
|
||||
return;
|
||||
}
|
||||
|
||||
cli_full_connection_creds_enc_start(req);
|
||||
}
|
||||
|
||||
static void cli_full_connection_creds_enc_start(struct tevent_req *req)
|
||||
{
|
||||
struct cli_full_connection_creds_state *state = tevent_req_data(
|
||||
req, struct cli_full_connection_creds_state);
|
||||
enum smb_encryption_setting encryption_state =
|
||||
cli_credentials_get_smb_encryption(state->creds);
|
||||
struct tevent_req *subreq = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (encryption_state < SMB_ENCRYPTION_DESIRED) {
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (smbXcli_conn_protocol(state->cli->conn) >= PROTOCOL_SMB2_02) {
|
||||
status = smb2cli_session_encryption_on(state->cli->smb2.session);
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
|
||||
if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
return;
|
||||
}
|
||||
d_printf("Encryption required and "
|
||||
"server doesn't support "
|
||||
"SMB3 encryption - failing connect\n");
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
} else if (!NT_STATUS_IS_OK(status)) {
|
||||
d_printf("Encryption required and "
|
||||
"setup failed with error %s.\n",
|
||||
nt_errstr(status));
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SERVER_HAS_UNIX_CIFS(state->cli)) {
|
||||
if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
return;
|
||||
}
|
||||
|
||||
status = NT_STATUS_NOT_SUPPORTED;
|
||||
d_printf("Encryption required and "
|
||||
"server doesn't support "
|
||||
"SMB1 Unix Extensions - failing connect\n");
|
||||
tevent_req_nterror(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do a tcon on IPC$ just to setup the encryption,
|
||||
* the real tcon will be encrypted then.
|
||||
*/
|
||||
subreq = cli_tree_connect_send(state, state->ev, state->cli,
|
||||
"IPC$", "IPC", NULL);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq, cli_full_connection_creds_enc_tcon, req);
|
||||
}
|
||||
|
||||
static void cli_full_connection_creds_enc_tcon(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct cli_full_connection_creds_state *state = tevent_req_data(
|
||||
req, struct cli_full_connection_creds_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = cli_tree_connect_recv(subreq);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
subreq = cli_unix_extensions_version_send(state, state->ev, state->cli);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq, cli_full_connection_creds_enc_ver, req);
|
||||
}
|
||||
|
||||
static void cli_full_connection_creds_enc_ver(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct cli_full_connection_creds_state *state = tevent_req_data(
|
||||
req, struct cli_full_connection_creds_state);
|
||||
enum smb_encryption_setting encryption_state =
|
||||
cli_credentials_get_smb_encryption(state->creds);
|
||||
uint16_t major, minor;
|
||||
uint32_t caplow, caphigh;
|
||||
NTSTATUS status;
|
||||
|
||||
status = cli_unix_extensions_version_recv(subreq,
|
||||
&major, &minor,
|
||||
&caplow,
|
||||
&caphigh);
|
||||
TALLOC_FREE(subreq);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
return;
|
||||
}
|
||||
DEBUG(10, ("%s: cli_unix_extensions_version "
|
||||
"returned %s\n", __func__, nt_errstr(status)));
|
||||
tevent_req_nterror(req, NT_STATUS_UNKNOWN_REVISION);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
|
||||
if (encryption_state < SMB_ENCRYPTION_REQUIRED) {
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
return;
|
||||
}
|
||||
DEBUG(10, ("%s: CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP "
|
||||
"not supported\n", __func__));
|
||||
tevent_req_nterror(req, NT_STATUS_UNSUPPORTED_COMPRESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
subreq = cli_smb1_setup_encryption_send(state, state->ev,
|
||||
state->cli,
|
||||
state->creds);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq,
|
||||
cli_full_connection_creds_enc_done,
|
||||
req);
|
||||
}
|
||||
|
||||
static void cli_full_connection_creds_enc_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
NTSTATUS status;
|
||||
|
||||
status = cli_smb1_setup_encryption_recv(subreq);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cli_full_connection_creds_tcon_start(req);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user