diff options
-rw-r--r-- | source3/client/client.c | 45 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 121 |
2 files changed, 145 insertions, 21 deletions
diff --git a/source3/client/client.c b/source3/client/client.c index 53669bc8d0..3d529981e5 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -93,6 +93,9 @@ static unsigned int put_total_time_ms = 0; /* totals globals */ static double dir_total; +/* encrypted state. */ +static bool smb_encrypt; + /* root cli_state connection */ struct cli_state *cli; @@ -2215,6 +2218,7 @@ static int cmd_posix_encrypt(void) d_printf("posix_encrypt failed with error %s\n", nt_errstr(status)); } else { d_printf("encryption on\n"); + smb_encrypt = true; } return 0; @@ -3786,16 +3790,28 @@ int cmd_iosize(void) int iosize; if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { - d_printf("iosize <n> or iosize 0x<n>. " - "Minimum is 16384 (0x4000), " - "max is 16776960 (0xFFFF00)\n"); + if (!smb_encrypt) { + d_printf("iosize <n> or iosize 0x<n>. " + "Minimum is 16384 (0x4000), " + "max is 16776960 (0xFFFF00)\n"); + } else { + d_printf("iosize <n> or iosize 0x<n>. " + "(Encrypted connection) ," + "Minimum is 16384 (0x4000), " + "max is 64512 (0xFC00)\n"); + } return 1; } iosize = strtol(buf,NULL,0); - if (iosize < 0 || iosize > 0xFFFF00) { + if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) { + d_printf("iosize out of range for encrypted " + "connection (min = 16384 (0x4000), " + "max = 16776960 (0xFC00)"); + return 1; + } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) { d_printf("iosize out of range (min = 16384 (0x4000), " - "max = 16776960 (0x0xFFFF00)"); + "max = 16776960 (0xFFFF00)"); return 1; } @@ -3971,7 +3987,8 @@ static int process_command_string(const char *cmd_in) /* establish the connection if not already */ if (!cli) { - cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true); + cli = cli_cm_open(talloc_tos(), NULL, desthost, + service, true, smb_encrypt); if (!cli) { return 1; } @@ -4396,7 +4413,8 @@ static int process(const char *base_directory) { int rc = 0; - cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true); + cli = cli_cm_open(talloc_tos(), NULL, + desthost, service, true, smb_encrypt); if (!cli) { return 1; } @@ -4425,7 +4443,8 @@ static int process(const char *base_directory) static int do_host_query(const char *query_host) { - cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true); + cli = cli_cm_open(talloc_tos(), NULL, + query_host, "IPC$", true, smb_encrypt); if (!cli) return 1; @@ -4438,7 +4457,8 @@ static int do_host_query(const char *query_host) cli_cm_shutdown(); cli_cm_set_port( 139 ); - cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true); + cli = cli_cm_open(talloc_tos(), NULL, + query_host, "IPC$", true, smb_encrypt); } if (cli == NULL) { @@ -4463,7 +4483,8 @@ static int do_tar_op(const char *base_directory) /* do we already have a connection? */ if (!cli) { - cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true); + cli = cli_cm_open(talloc_tos(), NULL, + desthost, service, true, smb_encrypt); if (!cli) return 1; } @@ -4571,6 +4592,7 @@ static int do_message_op(void) { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" }, { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" }, { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" }, + { "encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" }, POPT_COMMON_SAMBA POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS @@ -4713,6 +4735,9 @@ static int do_message_op(void) case 'g': grepable=true; break; + case 'e': + smb_encrypt=true; + break; case 'B': return(do_smb_browse()); diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index e0c40b52ed..7800d10e8b 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -58,6 +58,70 @@ static struct sockaddr_storage dest_ss; static struct client_connection *connections; +static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, + struct cli_state *cli, + const char *sharename, + char **pp_newserver, + char **pp_newshare, + bool force_encrypt, + const char *username, + const char *password, + const char *domain); + +/******************************************************************** + Ensure a connection is encrypted. +********************************************************************/ + +static bool force_cli_encryption(struct cli_state *c, + const char *username, + const char *password, + const char *domain, + const char *sharename) +{ + uint16 major, minor; + uint32 caplow, caphigh; + NTSTATUS status; + + if (!SERVER_HAS_UNIX_CIFS(c)) { + d_printf("Encryption required and " + "server that doesn't support " + "UNIX extensions - failing connect\n"); + return false; + } + + if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) { + d_printf("Encryption required and " + "can't get UNIX CIFS extensions " + "version from server.\n"); + return false; + } + + if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) { + d_printf("Encryption required and " + "share %s doesn't support " + "encryption.\n", sharename); + return false; + } + + if (c->use_kerberos) { + status = cli_gss_smb_encryption_start(c); + } else { + status = cli_raw_ntlm_smb_encryption_start(c, + username, + password, + domain); + } + + if (!NT_STATUS_IS_OK(status)) { + d_printf("Encryption required and " + "setup failed with error %s.\n", + nt_errstr(status)); + return false; + } + + return true; +} + /******************************************************************** Return a connection to a server. ********************************************************************/ @@ -65,7 +129,8 @@ static struct client_connection *connections; static struct cli_state *do_connect(TALLOC_CTX *ctx, const char *server, const char *share, - bool show_sessetup) + bool show_sessetup, + bool force_encrypt) { struct cli_state *c = NULL; struct nmb_name called, calling; @@ -197,9 +262,14 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, if ((c->capabilities & CAP_DFS) && cli_check_msdfs_proxy(ctx, c, sharename, - &newserver, &newshare)) { + &newserver, &newshare, + force_encrypt, + username, + password, + lp_workgroup())) { cli_shutdown(c); - return do_connect(ctx, newserver, newshare, false); + return do_connect(ctx, newserver, + newshare, false, force_encrypt); } /* must be a normal share */ @@ -211,6 +281,15 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx, return NULL; } + if (force_encrypt && !force_cli_encryption(c, + username, + password, + lp_workgroup(), + sharename)) { + cli_shutdown(c); + return NULL; + } + DEBUG(4,(" tconx ok\n")); return c; } @@ -269,7 +348,8 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx, struct cli_state *referring_cli, const char *server, const char *share, - bool show_hdr) + bool show_hdr, + bool force_encrypt) { struct client_connection *node; @@ -279,7 +359,7 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx, return NULL; } - node->cli = do_connect(ctx, server, share, show_hdr); + node->cli = do_connect(ctx, server, share, show_hdr, force_encrypt); if ( !node->cli ) { TALLOC_FREE( node ); @@ -331,7 +411,8 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx, struct cli_state *referring_cli, const char *server, const char *share, - bool show_hdr) + bool show_hdr, + bool force_encrypt) { struct cli_state *c; @@ -339,7 +420,8 @@ struct cli_state *cli_cm_open(TALLOC_CTX *ctx, c = cli_cm_find(server, share); if (!c) { - c = cli_cm_connect(ctx, referring_cli, server, share, show_hdr); + c = cli_cm_connect(ctx, referring_cli, + server, share, show_hdr, force_encrypt); } return c; @@ -776,7 +858,9 @@ bool cli_resolve_path(TALLOC_CTX *ctx, /* Check for the referral. */ if (!(cli_ipc = cli_cm_open(ctx, rootcli, - rootcli->desthost, "IPC$", false))) { + rootcli->desthost, + "IPC$", false, + (rootcli->trans_enc_state != NULL)))) { return false; } @@ -818,7 +902,10 @@ bool cli_resolve_path(TALLOC_CTX *ctx, /* Open the connection to the target server & share */ if ((*targetcli = cli_cm_open(ctx, rootcli, - server, share, false)) == NULL) { + server, + share, + false, + (rootcli->trans_enc_state != NULL))) == NULL) { d_printf("Unable to follow dfs referral [\\%s\\%s]\n", server, share ); return false; @@ -905,11 +992,15 @@ bool cli_resolve_path(TALLOC_CTX *ctx, /******************************************************************** ********************************************************************/ -bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, +static bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, struct cli_state *cli, const char *sharename, char **pp_newserver, - char **pp_newshare ) + char **pp_newshare, + bool force_encrypt, + const char *username, + const char *password, + const char *domain) { CLIENT_DFS_REFERRAL *refs = NULL; size_t num_refs = 0; @@ -944,6 +1035,14 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, return false; } + if (force_encrypt && !force_cli_encryption(cli, + username, + password, + lp_workgroup(), + "IPC$")) { + return false; + } + res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed); if (!cli_tdis(cli)) { |