Add the options smb_encrypt_level to set the requested
authorJeremy Allison <jra@samba.org>
Sat, 5 Jan 2008 08:51:18 +0000 (00:51 -0800)
committerJeremy Allison <jra@samba.org>
Sat, 5 Jan 2008 08:51:18 +0000 (00:51 -0800)
encrypt level and smb_encrypt_on to query it.
Jeremy.
(This used to be commit 07d47996f9535731ccdc1792c405c8bee1a082ae)

source3/include/libsmb_internal.h
source3/libsmb/libsmbclient.c

index 19a3edc9bfdb070bbc1a4254dc31b615d714af82..dbc115429b405c5019a42000bead37907b8316f3 100644 (file)
@@ -106,6 +106,13 @@ struct smbc_internal_data {
          * and retrieved with smbc_option_set() and smbc_option_get().
          */
         void * _user_data;
+
+        /*
+         * Should we attempt UNIX smb encryption ? 
+         * Set to 0 if we should never attempt, set to 1 if
+         * encryption requested, set to 2 if encryption required.
+         */
+        int _smb_encryption_level;
 };     
 
 
index 2ff28302561b5d14c96689a5aaf3a87c06fcf1bf..da8f1e332b44b39b7f2289933f91797fe97e940e 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) John Terpstra 2000
    Copyright (C) Tom Jansen (Ninja ISD) 2002 
    Copyright (C) Derrell Lipman 2003, 2004
+   Copyright (C) Jeremy Allison 2007, 2008
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -739,6 +740,12 @@ smbc_server(SMBCCTX *context,
                                         password, strlen(password)+1);
                         }
 
+                       /*
+                        * We don't need to renegotiate encryption
+                        * here as the encryption context is not per
+                        * tid.
+                        */
+
                         if (! cli_send_tconX(srv->cli, share, "?????",
                                              password, strlen(password)+1)) {
 
@@ -903,6 +910,30 @@ smbc_server(SMBCCTX *context,
 
        DEBUG(4,(" tconx ok\n"));
 
+       if (context->internal->_smb_encryption_level) {
+               /* Attempt UNIX smb encryption. */
+               if (!NT_STATUS_IS_OK(cli_force_encryption(c,
+                                               username_used,
+                                               password,
+                                               workgroup))) {
+
+                       /*
+                        * context->internal->_smb_encryption_level == 1
+                        * means don't fail if encryption can't be negotiated,
+                        * == 2 means fail if encryption can't be negotiated.
+                        */
+
+                       DEBUG(4,(" SMB encrypt failed\n"));
+
+                       if (context->internal->_smb_encryption_level == 2) {
+                               cli_shutdown(c);
+                               errno = EPERM;
+                               return NULL;
+                       }
+               }
+               DEBUG(4,(" SMB encrypt ok\n"));
+       }
+
        /*
         * Ok, we have got a nice connection
         * Let's allocate a server structure.
@@ -1019,6 +1050,30 @@ smbc_attr_server(SMBCCTX *context,
                         return NULL;
                 }
 
+               if (context->internal->_smb_encryption_level) {
+                       /* Attempt UNIX smb encryption. */
+                       if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
+                                               username,
+                                               password,
+                                               workgroup))) {
+
+                               /*
+                                * context->internal->_smb_encryption_level == 1
+                                * means don't fail if encryption can't be negotiated,
+                                * == 2 means fail if encryption can't be negotiated.
+                                */
+
+                               DEBUG(4,(" SMB encrypt failed on IPC$\n"));
+
+                               if (context->internal->_smb_encryption_level == 2) {
+                                       cli_shutdown(ipc_cli);
+                                       errno = EPERM;
+                                       return NULL;
+                               }
+                       }
+                       DEBUG(4,(" SMB encrypt ok on IPC$\n"));
+               }
+
                 ipc_srv = SMB_MALLOC_P(SMBCSRV);
                 if (!ipc_srv) {
                         errno = ENOMEM;
@@ -6724,6 +6779,7 @@ smbc_option_set(SMBCCTX *context,
                 bool b;
                 smbc_get_auth_data_with_context_fn auth_fn;
                 void *v;
+               const char *s;
         } option_value;
 
         va_start(ap, option_name);
@@ -6772,6 +6828,19 @@ smbc_option_set(SMBCCTX *context,
                  */
                 option_value.v = va_arg(ap, void *);
                 context->internal->_user_data = option_value.v;
+        } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+                /*
+                 * Save an encoded value for encryption level.
+                 * 0 = off, 1 = attempt, 2 = required.
+                 */
+                option_value.s = va_arg(ap, const char *);
+               if (strcmp(option_value.s, "none") == 0) {
+                       context->internal->_smb_encryption_level = 0;
+               } else if (strcmp(option_value.s, "request") == 0) {
+                       context->internal->_smb_encryption_level = 1;
+               } else if (strcmp(option_value.s, "require") == 0) {
+                       context->internal->_smb_encryption_level = 2;
+               }
         }
 
         va_end(ap);
@@ -6821,6 +6890,35 @@ smbc_option_get(SMBCCTX *context,
                  * with smbc_option_get()
                  */
                 return context->internal->_user_data;
+        } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
+               /*
+                * Return the current smb encrypt negotiate option as a string.
+                */
+               switch (context->internal->_smb_encryption_level) {
+               case 0:
+                       return (void *) "none";
+               case 1:
+                       return (void *) "request";
+               case 2:
+                       return (void *) "require";
+               }
+        } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
+               /*
+                * Return the current smb encrypt status option as a bool.
+                * false = off, true = on. We don't know what server is
+                * being requested, so we only return true if all servers
+                * are using an encrypted connection.
+                */
+               SMBCSRV *s;
+               unsigned int num_servers = 0;
+
+               for (s = context->internal->_servers; s; s = s->next) {
+                       num_servers++;
+                       if (s->cli->trans_enc_state == NULL) {
+                               return (void *)false;
+                       }
+               }
+               return (void *) (bool) (num_servers > 0);
         }
 
         return NULL;