Added -e, --encrypt option to smbclient that immediately
authorJeremy Allison <jra@samba.org>
Sun, 30 Dec 2007 06:39:52 +0000 (22:39 -0800)
committerJeremy Allison <jra@samba.org>
Sun, 30 Dec 2007 06:39:52 +0000 (22:39 -0800)
forces encrypted smb after initial connect. Will document
for 3.2 official release.
Jeremy.
(This used to be commit f02bf419282419950471deae74c4a6fe1543ed26)

source3/client/client.c
source3/libsmb/clidfs.c

index 53669bc8d093f74c59a1047daba3b59d343b8029..3d529981e5dde759577e3bdb0667b56b81e6a566 100644 (file)
@@ -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());
 
index e0c40b52ed269bf95dd24a89923ab4ba5dc95641..7800d10e8be39e39b643316020f4118cd79dcc90 100644 (file)
@@ -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)) {