You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by am...@apache.org on 2017/05/20 23:52:42 UTC

[1/6] drill git commit: DRILL-4335: Apache Drill should support network encryption.

Repository: drill
Updated Branches:
  refs/heads/master 416ec70a6 -> d11aba2e5


http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java b/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
index aa12f96..32e3d9c 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/UserProtos.java
@@ -491,6 +491,10 @@ public final class UserProtos {
      * <code>SASL_AUTH = 1;</code>
      */
     SASL_AUTH(1, 1),
+    /**
+     * <code>SASL_PRIVACY = 2;</code>
+     */
+    SASL_PRIVACY(2, 2),
     ;
 
     /**
@@ -501,6 +505,10 @@ public final class UserProtos {
      * <code>SASL_AUTH = 1;</code>
      */
     public static final int SASL_AUTH_VALUE = 1;
+    /**
+     * <code>SASL_PRIVACY = 2;</code>
+     */
+    public static final int SASL_PRIVACY_VALUE = 2;
 
 
     public final int getNumber() { return value; }
@@ -509,6 +517,7 @@ public final class UserProtos {
       switch (value) {
         case 0: return UNKNOWN_SASL_SUPPORT;
         case 1: return SASL_AUTH;
+        case 2: return SASL_PRIVACY;
         default: return null;
       }
     }
@@ -9567,6 +9576,26 @@ public final class UserProtos {
      * <code>repeated .exec.user.RpcType supported_methods = 8;</code>
      */
     org.apache.drill.exec.proto.UserProtos.RpcType getSupportedMethods(int index);
+
+    // optional bool encrypted = 9;
+    /**
+     * <code>optional bool encrypted = 9;</code>
+     */
+    boolean hasEncrypted();
+    /**
+     * <code>optional bool encrypted = 9;</code>
+     */
+    boolean getEncrypted();
+
+    // optional int32 maxWrappedSize = 10;
+    /**
+     * <code>optional int32 maxWrappedSize = 10;</code>
+     */
+    boolean hasMaxWrappedSize();
+    /**
+     * <code>optional int32 maxWrappedSize = 10;</code>
+     */
+    int getMaxWrappedSize();
   }
   /**
    * Protobuf type {@code exec.user.BitToUserHandshake}
@@ -9699,6 +9728,16 @@ public final class UserProtos {
               input.popLimit(oldLimit);
               break;
             }
+            case 72: {
+              bitField0_ |= 0x00000020;
+              encrypted_ = input.readBool();
+              break;
+            }
+            case 80: {
+              bitField0_ |= 0x00000040;
+              maxWrappedSize_ = input.readInt32();
+              break;
+            }
           }
         }
       } catch (com.google.protobuf.InvalidProtocolBufferException e) {
@@ -9937,6 +9976,38 @@ public final class UserProtos {
       return supportedMethods_.get(index);
     }
 
+    // optional bool encrypted = 9;
+    public static final int ENCRYPTED_FIELD_NUMBER = 9;
+    private boolean encrypted_;
+    /**
+     * <code>optional bool encrypted = 9;</code>
+     */
+    public boolean hasEncrypted() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional bool encrypted = 9;</code>
+     */
+    public boolean getEncrypted() {
+      return encrypted_;
+    }
+
+    // optional int32 maxWrappedSize = 10;
+    public static final int MAXWRAPPEDSIZE_FIELD_NUMBER = 10;
+    private int maxWrappedSize_;
+    /**
+     * <code>optional int32 maxWrappedSize = 10;</code>
+     */
+    public boolean hasMaxWrappedSize() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>optional int32 maxWrappedSize = 10;</code>
+     */
+    public int getMaxWrappedSize() {
+      return maxWrappedSize_;
+    }
+
     private void initFields() {
       rpcVersion_ = 0;
       status_ = org.apache.drill.exec.proto.UserProtos.HandshakeStatus.SUCCESS;
@@ -9945,6 +10016,8 @@ public final class UserProtos {
       serverInfos_ = org.apache.drill.exec.proto.UserProtos.RpcEndpointInfos.getDefaultInstance();
       authenticationMechanisms_ = com.google.protobuf.LazyStringArrayList.EMPTY;
       supportedMethods_ = java.util.Collections.emptyList();
+      encrypted_ = false;
+      maxWrappedSize_ = 0;
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
@@ -9979,6 +10052,12 @@ public final class UserProtos {
       for (int i = 0; i < supportedMethods_.size(); i++) {
         output.writeEnum(8, supportedMethods_.get(i).getNumber());
       }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeBool(9, encrypted_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeInt32(10, maxWrappedSize_);
+      }
       getUnknownFields().writeTo(output);
     }
 
@@ -10026,6 +10105,14 @@ public final class UserProtos {
         size += dataSize;
         size += 1 * supportedMethods_.size();
       }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(9, encrypted_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(10, maxWrappedSize_);
+      }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
       return size;
@@ -10161,6 +10248,10 @@ public final class UserProtos {
         bitField0_ = (bitField0_ & ~0x00000020);
         supportedMethods_ = java.util.Collections.emptyList();
         bitField0_ = (bitField0_ & ~0x00000040);
+        encrypted_ = false;
+        bitField0_ = (bitField0_ & ~0x00000080);
+        maxWrappedSize_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000100);
         return this;
       }
 
@@ -10224,6 +10315,14 @@ public final class UserProtos {
           bitField0_ = (bitField0_ & ~0x00000040);
         }
         result.supportedMethods_ = supportedMethods_;
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.encrypted_ = encrypted_;
+        if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+          to_bitField0_ |= 0x00000040;
+        }
+        result.maxWrappedSize_ = maxWrappedSize_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
@@ -10279,6 +10378,12 @@ public final class UserProtos {
           }
           onChanged();
         }
+        if (other.hasEncrypted()) {
+          setEncrypted(other.getEncrypted());
+        }
+        if (other.hasMaxWrappedSize()) {
+          setMaxWrappedSize(other.getMaxWrappedSize());
+        }
         this.mergeUnknownFields(other.getUnknownFields());
         return this;
       }
@@ -10805,6 +10910,72 @@ public final class UserProtos {
         return this;
       }
 
+      // optional bool encrypted = 9;
+      private boolean encrypted_ ;
+      /**
+       * <code>optional bool encrypted = 9;</code>
+       */
+      public boolean hasEncrypted() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional bool encrypted = 9;</code>
+       */
+      public boolean getEncrypted() {
+        return encrypted_;
+      }
+      /**
+       * <code>optional bool encrypted = 9;</code>
+       */
+      public Builder setEncrypted(boolean value) {
+        bitField0_ |= 0x00000080;
+        encrypted_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool encrypted = 9;</code>
+       */
+      public Builder clearEncrypted() {
+        bitField0_ = (bitField0_ & ~0x00000080);
+        encrypted_ = false;
+        onChanged();
+        return this;
+      }
+
+      // optional int32 maxWrappedSize = 10;
+      private int maxWrappedSize_ ;
+      /**
+       * <code>optional int32 maxWrappedSize = 10;</code>
+       */
+      public boolean hasMaxWrappedSize() {
+        return ((bitField0_ & 0x00000100) == 0x00000100);
+      }
+      /**
+       * <code>optional int32 maxWrappedSize = 10;</code>
+       */
+      public int getMaxWrappedSize() {
+        return maxWrappedSize_;
+      }
+      /**
+       * <code>optional int32 maxWrappedSize = 10;</code>
+       */
+      public Builder setMaxWrappedSize(int value) {
+        bitField0_ |= 0x00000100;
+        maxWrappedSize_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 maxWrappedSize = 10;</code>
+       */
+      public Builder clearMaxWrappedSize() {
+        bitField0_ = (bitField0_ & ~0x00000100);
+        maxWrappedSize_ = 0;
+        onChanged();
+        return this;
+      }
+
       // @@protoc_insertion_point(builder_scope:exec.user.BitToUserHandshake)
     }
 
@@ -41665,198 +41836,200 @@ public final class UserProtos {
       "ed.QueryResult.QueryState\022&\n\010query_id\030\002 " +
       "\001(\0132\024.exec.shared.QueryId\0221\n\tfragments\030\003" +
       " \003(\0132\036.exec.bit.control.PlanFragment\022(\n\005" +
-      "error\030\004 \001(\0132\031.exec.shared.DrillPBError\"\200",
+      "error\030\004 \001(\0132\031.exec.shared.DrillPBError\"\253",
       "\002\n\022BitToUserHandshake\022\023\n\013rpc_version\030\002 \001" +
       "(\005\022*\n\006status\030\003 \001(\0162\032.exec.user.Handshake" +
       "Status\022\017\n\007errorId\030\004 \001(\t\022\024\n\014errorMessage\030" +
       "\005 \001(\t\0221\n\014server_infos\030\006 \001(\0132\033.exec.user." +
       "RpcEndpointInfos\022 \n\030authenticationMechan" +
       "isms\030\007 \003(\t\022-\n\021supported_methods\030\010 \003(\0162\022." +
-      "exec.user.RpcType\"-\n\nLikeFilter\022\017\n\007patte" +
-      "rn\030\001 \001(\t\022\016\n\006escape\030\002 \001(\t\"D\n\016GetCatalogsR" +
-      "eq\0222\n\023catalog_name_filter\030\001 \001(\0132\025.exec.u" +
-      "ser.LikeFilter\"M\n\017CatalogMetadata\022\024\n\014cat",
-      "alog_name\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022\017\n\007" +
-      "connect\030\003 \001(\t\"\223\001\n\017GetCatalogsResp\022(\n\006sta" +
-      "tus\030\001 \001(\0162\030.exec.user.RequestStatus\022,\n\010c" +
-      "atalogs\030\002 \003(\0132\032.exec.user.CatalogMetadat" +
-      "a\022(\n\005error\030\003 \001(\0132\031.exec.shared.DrillPBEr" +
-      "ror\"v\n\rGetSchemasReq\0222\n\023catalog_name_fil" +
-      "ter\030\001 \001(\0132\025.exec.user.LikeFilter\0221\n\022sche" +
-      "ma_name_filter\030\002 \001(\0132\025.exec.user.LikeFil" +
-      "ter\"i\n\016SchemaMetadata\022\024\n\014catalog_name\030\001 " +
-      "\001(\t\022\023\n\013schema_name\030\002 \001(\t\022\r\n\005owner\030\003 \001(\t\022",
-      "\014\n\004type\030\004 \001(\t\022\017\n\007mutable\030\005 \001(\t\"\220\001\n\016GetSc" +
-      "hemasResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Re" +
-      "questStatus\022*\n\007schemas\030\002 \003(\0132\031.exec.user" +
-      ".SchemaMetadata\022(\n\005error\030\003 \001(\0132\031.exec.sh" +
-      "ared.DrillPBError\"\302\001\n\014GetTablesReq\0222\n\023ca" +
-      "talog_name_filter\030\001 \001(\0132\025.exec.user.Like" +
-      "Filter\0221\n\022schema_name_filter\030\002 \001(\0132\025.exe" +
-      "c.user.LikeFilter\0220\n\021table_name_filter\030\003" +
-      " \001(\0132\025.exec.user.LikeFilter\022\031\n\021table_typ" +
-      "e_filter\030\004 \003(\t\"\\\n\rTableMetadata\022\024\n\014catal",
-      "og_name\030\001 \001(\t\022\023\n\013schema_name\030\002 \001(\t\022\022\n\nta" +
-      "ble_name\030\003 \001(\t\022\014\n\004type\030\004 \001(\t\"\215\001\n\rGetTabl" +
-      "esResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Reque" +
-      "stStatus\022(\n\006tables\030\002 \003(\0132\030.exec.user.Tab" +
-      "leMetadata\022(\n\005error\030\003 \001(\0132\031.exec.shared." +
-      "DrillPBError\"\333\001\n\rGetColumnsReq\0222\n\023catalo" +
-      "g_name_filter\030\001 \001(\0132\025.exec.user.LikeFilt" +
-      "er\0221\n\022schema_name_filter\030\002 \001(\0132\025.exec.us" +
-      "er.LikeFilter\0220\n\021table_name_filter\030\003 \001(\013" +
-      "2\025.exec.user.LikeFilter\0221\n\022column_name_f",
-      "ilter\030\004 \001(\0132\025.exec.user.LikeFilter\"\251\003\n\016C" +
-      "olumnMetadata\022\024\n\014catalog_name\030\001 \001(\t\022\023\n\013s" +
-      "chema_name\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022\023\n\013" +
-      "column_name\030\004 \001(\t\022\030\n\020ordinal_position\030\005 " +
-      "\001(\005\022\025\n\rdefault_value\030\006 \001(\t\022\023\n\013is_nullabl" +
-      "e\030\007 \001(\010\022\021\n\tdata_type\030\010 \001(\t\022\027\n\017char_max_l" +
-      "ength\030\t \001(\005\022\031\n\021char_octet_length\030\n \001(\005\022\031" +
-      "\n\021numeric_precision\030\013 \001(\005\022\037\n\027numeric_pre" +
-      "cision_radix\030\014 \001(\005\022\025\n\rnumeric_scale\030\r \001(" +
-      "\005\022\033\n\023date_time_precision\030\016 \001(\005\022\025\n\rinterv",
-      "al_type\030\017 \001(\t\022\032\n\022interval_precision\030\020 \001(" +
-      "\005\022\023\n\013column_size\030\021 \001(\005\"\220\001\n\016GetColumnsRes" +
-      "p\022(\n\006status\030\001 \001(\0162\030.exec.user.RequestSta" +
-      "tus\022*\n\007columns\030\002 \003(\0132\031.exec.user.ColumnM" +
-      "etadata\022(\n\005error\030\003 \001(\0132\031.exec.shared.Dri" +
-      "llPBError\"/\n\032CreatePreparedStatementReq\022" +
-      "\021\n\tsql_query\030\001 \001(\t\"\326\003\n\024ResultColumnMetad" +
-      "ata\022\024\n\014catalog_name\030\001 \001(\t\022\023\n\013schema_name" +
-      "\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022\023\n\013column_nam" +
-      "e\030\004 \001(\t\022\r\n\005label\030\005 \001(\t\022\021\n\tdata_type\030\006 \001(",
-      "\t\022\023\n\013is_nullable\030\007 \001(\010\022\021\n\tprecision\030\010 \001(" +
-      "\005\022\r\n\005scale\030\t \001(\005\022\016\n\006signed\030\n \001(\010\022\024\n\014disp" +
-      "lay_size\030\013 \001(\005\022\022\n\nis_aliased\030\014 \001(\010\0225\n\rse" +
-      "archability\030\r \001(\0162\036.exec.user.ColumnSear" +
-      "chability\0223\n\014updatability\030\016 \001(\0162\035.exec.u" +
-      "ser.ColumnUpdatability\022\026\n\016auto_increment" +
-      "\030\017 \001(\010\022\030\n\020case_sensitivity\030\020 \001(\010\022\020\n\010sort" +
-      "able\030\021 \001(\010\022\022\n\nclass_name\030\022 \001(\t\022\023\n\013is_cur" +
-      "rency\030\024 \001(\010\".\n\027PreparedStatementHandle\022\023" +
-      "\n\013server_info\030\001 \001(\014\"\200\001\n\021PreparedStatemen",
-      "t\0220\n\007columns\030\001 \003(\0132\037.exec.user.ResultCol" +
-      "umnMetadata\0229\n\rserver_handle\030\002 \001(\0132\".exe" +
-      "c.user.PreparedStatementHandle\"\253\001\n\033Creat" +
-      "ePreparedStatementResp\022(\n\006status\030\001 \001(\0162\030" +
-      ".exec.user.RequestStatus\0228\n\022prepared_sta" +
-      "tement\030\002 \001(\0132\034.exec.user.PreparedStateme" +
-      "nt\022(\n\005error\030\003 \001(\0132\031.exec.shared.DrillPBE" +
-      "rror\"\022\n\020GetServerMetaReq\"P\n\016ConvertSuppo" +
-      "rt\022\037\n\004from\030\001 \002(\0162\021.common.MinorType\022\035\n\002t" +
-      "o\030\002 \002(\0162\021.common.MinorType\"\223\001\n\021GetServer",
-      "MetaResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Req" +
-      "uestStatus\022*\n\013server_meta\030\002 \001(\0132\025.exec.u" +
-      "ser.ServerMeta\022(\n\005error\030\003 \001(\0132\031.exec.sha" +
-      "red.DrillPBError\"\377\r\n\nServerMeta\022\035\n\025all_t" +
-      "ables_selectable\030\001 \001(\010\022%\n\035blob_included_" +
-      "in_max_row_size\030\002 \001(\010\022\030\n\020catalog_at_star" +
-      "t\030\003 \001(\010\022\031\n\021catalog_separator\030\004 \001(\t\022\024\n\014ca" +
-      "talog_term\030\005 \001(\t\0222\n\017collate_support\030\006 \003(" +
-      "\0162\031.exec.user.CollateSupport\022!\n\031column_a" +
-      "liasing_supported\030\007 \001(\010\0222\n\017convert_suppo",
-      "rt\030\010 \003(\0132\031.exec.user.ConvertSupport\022E\n\031c" +
-      "orrelation_names_support\030\t \001(\0162\".exec.us" +
-      "er.CorrelationNamesSupport\022\033\n\023date_time_" +
-      "functions\030\n \003(\t\022F\n\032date_time_literals_su" +
-      "pport\030\013 \003(\0162\".exec.user.DateTimeLiterals" +
-      "Support\0223\n\020group_by_support\030\014 \001(\0162\031.exec" +
-      ".user.GroupBySupport\0226\n\021identifier_casin" +
-      "g\030\r \001(\0162\033.exec.user.IdentifierCasing\022\037\n\027" +
-      "identifier_quote_string\030\016 \001(\t\022$\n\034like_es" +
-      "cape_clause_supported\030\017 \001(\010\022!\n\031max_binar",
-      "y_literal_length\030\020 \001(\r\022\037\n\027max_catalog_na" +
-      "me_length\030\021 \001(\r\022\037\n\027max_char_literal_leng" +
-      "th\030\022 \001(\r\022\036\n\026max_column_name_length\030\023 \001(\r" +
-      "\022\037\n\027max_columns_in_group_by\030\024 \001(\r\022\037\n\027max" +
-      "_columns_in_order_by\030\025 \001(\r\022\035\n\025max_column" +
-      "s_in_select\030\026 \001(\r\022\036\n\026max_cursor_name_len" +
-      "gth\030\027 \001(\r\022\034\n\024max_logical_lob_size\030\030 \001(\r\022" +
-      "\024\n\014max_row_size\030\031 \001(\r\022\036\n\026max_schema_name" +
-      "_length\030\032 \001(\r\022\034\n\024max_statement_length\030\033 " +
-      "\001(\r\022\026\n\016max_statements\030\034 \001(\r\022\035\n\025max_table",
-      "_name_length\030\035 \001(\r\022\034\n\024max_tables_in_sele" +
-      "ct\030\036 \001(\r\022\034\n\024max_user_name_length\030\037 \001(\r\0220" +
-      "\n\016null_collation\030  \001(\0162\030.exec.user.NullC" +
-      "ollation\022&\n\036null_plus_non_null_equals_nu" +
-      "ll\030! \001(\010\022\031\n\021numeric_functions\030\" \003(\t\0223\n\020o" +
-      "rder_by_support\030# \003(\0162\031.exec.user.OrderB" +
-      "ySupport\0227\n\022outer_join_support\030$ \003(\0162\033.e" +
-      "xec.user.OuterJoinSupport\022=\n\030quoted_iden" +
-      "tifier_casing\030% \001(\0162\033.exec.user.Identifi" +
-      "erCasing\022\021\n\tread_only\030& \001(\010\022\023\n\013schema_te",
-      "rm\030\' \001(\t\022\034\n\024search_escape_string\030( \001(\t\022#" +
-      "\n\033select_for_update_supported\030) \001(\010\022\032\n\022s" +
-      "pecial_characters\030* \001(\t\022\024\n\014sql_keywords\030" +
-      "+ \003(\t\022\030\n\020string_functions\030, \003(\t\0224\n\020subqu" +
-      "ery_support\030- \003(\0162\032.exec.user.SubQuerySu" +
-      "pport\022\030\n\020system_functions\030. \003(\t\022\022\n\ntable" +
-      "_term\030/ \001(\t\022\035\n\025transaction_supported\0300 \001" +
-      "(\010\022.\n\runion_support\0301 \003(\0162\027.exec.user.Un" +
-      "ionSupport\"\353\001\n\010RunQuery\0221\n\014results_mode\030" +
-      "\001 \001(\0162\033.exec.user.QueryResultsMode\022$\n\004ty",
-      "pe\030\002 \001(\0162\026.exec.shared.QueryType\022\014\n\004plan" +
-      "\030\003 \001(\t\0221\n\tfragments\030\004 \003(\0132\036.exec.bit.con" +
-      "trol.PlanFragment\022E\n\031prepared_statement_" +
-      "handle\030\005 \001(\0132\".exec.user.PreparedStateme" +
-      "ntHandle*\320\003\n\007RpcType\022\r\n\tHANDSHAKE\020\000\022\007\n\003A" +
-      "CK\020\001\022\013\n\007GOODBYE\020\002\022\r\n\tRUN_QUERY\020\003\022\020\n\014CANC" +
-      "EL_QUERY\020\004\022\023\n\017REQUEST_RESULTS\020\005\022\027\n\023RESUM" +
-      "E_PAUSED_QUERY\020\013\022\034\n\030GET_QUERY_PLAN_FRAGM" +
-      "ENTS\020\014\022\020\n\014GET_CATALOGS\020\016\022\017\n\013GET_SCHEMAS\020" +
-      "\017\022\016\n\nGET_TABLES\020\020\022\017\n\013GET_COLUMNS\020\021\022\035\n\031CR",
-      "EATE_PREPARED_STATEMENT\020\026\022\023\n\017GET_SERVER_" +
-      "META\020\010\022\016\n\nQUERY_DATA\020\006\022\020\n\014QUERY_HANDLE\020\007" +
-      "\022\030\n\024QUERY_PLAN_FRAGMENTS\020\r\022\014\n\010CATALOGS\020\022" +
-      "\022\013\n\007SCHEMAS\020\023\022\n\n\006TABLES\020\024\022\013\n\007COLUMNS\020\025\022\026" +
-      "\n\022PREPARED_STATEMENT\020\027\022\017\n\013SERVER_META\020\t\022" +
-      "\020\n\014QUERY_RESULT\020\n\022\020\n\014SASL_MESSAGE\020\030*6\n\013S" +
-      "aslSupport\022\030\n\024UNKNOWN_SASL_SUPPORT\020\000\022\r\n\t" +
-      "SASL_AUTH\020\001*#\n\020QueryResultsMode\022\017\n\013STREA" +
-      "M_FULL\020\001*q\n\017HandshakeStatus\022\013\n\007SUCCESS\020\001" +
-      "\022\030\n\024RPC_VERSION_MISMATCH\020\002\022\017\n\013AUTH_FAILE",
-      "D\020\003\022\023\n\017UNKNOWN_FAILURE\020\004\022\021\n\rAUTH_REQUIRE" +
-      "D\020\005*D\n\rRequestStatus\022\022\n\016UNKNOWN_STATUS\020\000" +
-      "\022\006\n\002OK\020\001\022\n\n\006FAILED\020\002\022\013\n\007TIMEOUT\020\003*Y\n\023Col" +
-      "umnSearchability\022\031\n\025UNKNOWN_SEARCHABILIT" +
-      "Y\020\000\022\010\n\004NONE\020\001\022\010\n\004CHAR\020\002\022\n\n\006NUMBER\020\003\022\007\n\003A" +
-      "LL\020\004*K\n\022ColumnUpdatability\022\030\n\024UNKNOWN_UP" +
-      "DATABILITY\020\000\022\r\n\tREAD_ONLY\020\001\022\014\n\010WRITABLE\020" +
-      "\002*1\n\016CollateSupport\022\016\n\nCS_UNKNOWN\020\000\022\017\n\013C" +
-      "S_GROUP_BY\020\001*J\n\027CorrelationNamesSupport\022" +
-      "\013\n\007CN_NONE\020\001\022\026\n\022CN_DIFFERENT_NAMES\020\002\022\n\n\006",
-      "CN_ANY\020\003*\271\003\n\027DateTimeLiteralsSupport\022\016\n\n" +
-      "DL_UNKNOWN\020\000\022\013\n\007DL_DATE\020\001\022\013\n\007DL_TIME\020\002\022\020" +
-      "\n\014DL_TIMESTAMP\020\003\022\024\n\020DL_INTERVAL_YEAR\020\004\022\025" +
-      "\n\021DL_INTERVAL_MONTH\020\005\022\023\n\017DL_INTERVAL_DAY" +
-      "\020\006\022\024\n\020DL_INTERVAL_HOUR\020\007\022\026\n\022DL_INTERVAL_" +
-      "MINUTE\020\010\022\026\n\022DL_INTERVAL_SECOND\020\t\022\035\n\031DL_I" +
-      "NTERVAL_YEAR_TO_MONTH\020\n\022\033\n\027DL_INTERVAL_D" +
-      "AY_TO_HOUR\020\013\022\035\n\031DL_INTERVAL_DAY_TO_MINUT" +
-      "E\020\014\022\035\n\031DL_INTERVAL_DAY_TO_SECOND\020\r\022\036\n\032DL" +
-      "_INTERVAL_HOUR_TO_MINUTE\020\016\022\036\n\032DL_INTERVA",
-      "L_HOUR_TO_SECOND\020\017\022 \n\034DL_INTERVAL_MINUTE" +
-      "_TO_SECOND\020\020*Y\n\016GroupBySupport\022\013\n\007GB_NON" +
-      "E\020\001\022\022\n\016GB_SELECT_ONLY\020\002\022\024\n\020GB_BEYOND_SEL" +
-      "ECT\020\003\022\020\n\014GB_UNRELATED\020\004*x\n\020IdentifierCas" +
-      "ing\022\016\n\nIC_UNKNOWN\020\000\022\023\n\017IC_STORES_LOWER\020\001" +
-      "\022\023\n\017IC_STORES_MIXED\020\002\022\023\n\017IC_STORES_UPPER" +
-      "\020\003\022\025\n\021IC_SUPPORTS_MIXED\020\004*X\n\rNullCollati" +
-      "on\022\016\n\nNC_UNKNOWN\020\000\022\017\n\013NC_AT_START\020\001\022\r\n\tN" +
-      "C_AT_END\020\002\022\013\n\007NC_HIGH\020\003\022\n\n\006NC_LOW\020\004*E\n\016O" +
-      "rderBySupport\022\016\n\nOB_UNKNOWN\020\000\022\020\n\014OB_UNRE",
-      "LATED\020\001\022\021\n\rOB_EXPRESSION\020\002*\226\001\n\020OuterJoin" +
-      "Support\022\016\n\nOJ_UNKNOWN\020\000\022\013\n\007OJ_LEFT\020\001\022\014\n\010" +
-      "OJ_RIGHT\020\002\022\013\n\007OJ_FULL\020\003\022\r\n\tOJ_NESTED\020\004\022\022" +
-      "\n\016OJ_NOT_ORDERED\020\005\022\014\n\010OJ_INNER\020\006\022\031\n\025OJ_A" +
-      "LL_COMPARISON_OPS\020\007*\204\001\n\017SubQuerySupport\022" +
-      "\016\n\nSQ_UNKNOWN\020\000\022\021\n\rSQ_CORRELATED\020\001\022\024\n\020SQ" +
-      "_IN_COMPARISON\020\002\022\020\n\014SQ_IN_EXISTS\020\003\022\020\n\014SQ" +
-      "_IN_INSERT\020\004\022\024\n\020SQ_IN_QUANTIFIED\020\005*;\n\014Un" +
-      "ionSupport\022\r\n\tU_UNKNOWN\020\000\022\013\n\007U_UNION\020\001\022\017" +
-      "\n\013U_UNION_ALL\020\002B+\n\033org.apache.drill.exec",
-      ".protoB\nUserProtosH\001"
+      "exec.user.RpcType\022\021\n\tencrypted\030\t \001(\010\022\026\n\016" +
+      "maxWrappedSize\030\n \001(\005\"-\n\nLikeFilter\022\017\n\007pa" +
+      "ttern\030\001 \001(\t\022\016\n\006escape\030\002 \001(\t\"D\n\016GetCatalo" +
+      "gsReq\0222\n\023catalog_name_filter\030\001 \001(\0132\025.exe",
+      "c.user.LikeFilter\"M\n\017CatalogMetadata\022\024\n\014" +
+      "catalog_name\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022" +
+      "\017\n\007connect\030\003 \001(\t\"\223\001\n\017GetCatalogsResp\022(\n\006" +
+      "status\030\001 \001(\0162\030.exec.user.RequestStatus\022," +
+      "\n\010catalogs\030\002 \003(\0132\032.exec.user.CatalogMeta" +
+      "data\022(\n\005error\030\003 \001(\0132\031.exec.shared.DrillP" +
+      "BError\"v\n\rGetSchemasReq\0222\n\023catalog_name_" +
+      "filter\030\001 \001(\0132\025.exec.user.LikeFilter\0221\n\022s" +
+      "chema_name_filter\030\002 \001(\0132\025.exec.user.Like" +
+      "Filter\"i\n\016SchemaMetadata\022\024\n\014catalog_name",
+      "\030\001 \001(\t\022\023\n\013schema_name\030\002 \001(\t\022\r\n\005owner\030\003 \001" +
+      "(\t\022\014\n\004type\030\004 \001(\t\022\017\n\007mutable\030\005 \001(\t\"\220\001\n\016Ge" +
+      "tSchemasResp\022(\n\006status\030\001 \001(\0162\030.exec.user" +
+      ".RequestStatus\022*\n\007schemas\030\002 \003(\0132\031.exec.u" +
+      "ser.SchemaMetadata\022(\n\005error\030\003 \001(\0132\031.exec" +
+      ".shared.DrillPBError\"\302\001\n\014GetTablesReq\0222\n" +
+      "\023catalog_name_filter\030\001 \001(\0132\025.exec.user.L" +
+      "ikeFilter\0221\n\022schema_name_filter\030\002 \001(\0132\025." +
+      "exec.user.LikeFilter\0220\n\021table_name_filte" +
+      "r\030\003 \001(\0132\025.exec.user.LikeFilter\022\031\n\021table_",
+      "type_filter\030\004 \003(\t\"\\\n\rTableMetadata\022\024\n\014ca" +
+      "talog_name\030\001 \001(\t\022\023\n\013schema_name\030\002 \001(\t\022\022\n" +
+      "\ntable_name\030\003 \001(\t\022\014\n\004type\030\004 \001(\t\"\215\001\n\rGetT" +
+      "ablesResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Re" +
+      "questStatus\022(\n\006tables\030\002 \003(\0132\030.exec.user." +
+      "TableMetadata\022(\n\005error\030\003 \001(\0132\031.exec.shar" +
+      "ed.DrillPBError\"\333\001\n\rGetColumnsReq\0222\n\023cat" +
+      "alog_name_filter\030\001 \001(\0132\025.exec.user.LikeF" +
+      "ilter\0221\n\022schema_name_filter\030\002 \001(\0132\025.exec" +
+      ".user.LikeFilter\0220\n\021table_name_filter\030\003 ",
+      "\001(\0132\025.exec.user.LikeFilter\0221\n\022column_nam" +
+      "e_filter\030\004 \001(\0132\025.exec.user.LikeFilter\"\251\003" +
+      "\n\016ColumnMetadata\022\024\n\014catalog_name\030\001 \001(\t\022\023" +
+      "\n\013schema_name\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022" +
+      "\023\n\013column_name\030\004 \001(\t\022\030\n\020ordinal_position" +
+      "\030\005 \001(\005\022\025\n\rdefault_value\030\006 \001(\t\022\023\n\013is_null" +
+      "able\030\007 \001(\010\022\021\n\tdata_type\030\010 \001(\t\022\027\n\017char_ma" +
+      "x_length\030\t \001(\005\022\031\n\021char_octet_length\030\n \001(" +
+      "\005\022\031\n\021numeric_precision\030\013 \001(\005\022\037\n\027numeric_" +
+      "precision_radix\030\014 \001(\005\022\025\n\rnumeric_scale\030\r",
+      " \001(\005\022\033\n\023date_time_precision\030\016 \001(\005\022\025\n\rint" +
+      "erval_type\030\017 \001(\t\022\032\n\022interval_precision\030\020" +
+      " \001(\005\022\023\n\013column_size\030\021 \001(\005\"\220\001\n\016GetColumns" +
+      "Resp\022(\n\006status\030\001 \001(\0162\030.exec.user.Request" +
+      "Status\022*\n\007columns\030\002 \003(\0132\031.exec.user.Colu" +
+      "mnMetadata\022(\n\005error\030\003 \001(\0132\031.exec.shared." +
+      "DrillPBError\"/\n\032CreatePreparedStatementR" +
+      "eq\022\021\n\tsql_query\030\001 \001(\t\"\326\003\n\024ResultColumnMe" +
+      "tadata\022\024\n\014catalog_name\030\001 \001(\t\022\023\n\013schema_n" +
+      "ame\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022\023\n\013column_",
+      "name\030\004 \001(\t\022\r\n\005label\030\005 \001(\t\022\021\n\tdata_type\030\006" +
+      " \001(\t\022\023\n\013is_nullable\030\007 \001(\010\022\021\n\tprecision\030\010" +
+      " \001(\005\022\r\n\005scale\030\t \001(\005\022\016\n\006signed\030\n \001(\010\022\024\n\014d" +
+      "isplay_size\030\013 \001(\005\022\022\n\nis_aliased\030\014 \001(\010\0225\n" +
+      "\rsearchability\030\r \001(\0162\036.exec.user.ColumnS" +
+      "earchability\0223\n\014updatability\030\016 \001(\0162\035.exe" +
+      "c.user.ColumnUpdatability\022\026\n\016auto_increm" +
+      "ent\030\017 \001(\010\022\030\n\020case_sensitivity\030\020 \001(\010\022\020\n\010s" +
+      "ortable\030\021 \001(\010\022\022\n\nclass_name\030\022 \001(\t\022\023\n\013is_" +
+      "currency\030\024 \001(\010\".\n\027PreparedStatementHandl",
+      "e\022\023\n\013server_info\030\001 \001(\014\"\200\001\n\021PreparedState" +
+      "ment\0220\n\007columns\030\001 \003(\0132\037.exec.user.Result" +
+      "ColumnMetadata\0229\n\rserver_handle\030\002 \001(\0132\"." +
+      "exec.user.PreparedStatementHandle\"\253\001\n\033Cr" +
+      "eatePreparedStatementResp\022(\n\006status\030\001 \001(" +
+      "\0162\030.exec.user.RequestStatus\0228\n\022prepared_" +
+      "statement\030\002 \001(\0132\034.exec.user.PreparedStat" +
+      "ement\022(\n\005error\030\003 \001(\0132\031.exec.shared.Drill" +
+      "PBError\"\022\n\020GetServerMetaReq\"P\n\016ConvertSu" +
+      "pport\022\037\n\004from\030\001 \002(\0162\021.common.MinorType\022\035",
+      "\n\002to\030\002 \002(\0162\021.common.MinorType\"\223\001\n\021GetSer" +
+      "verMetaResp\022(\n\006status\030\001 \001(\0162\030.exec.user." +
+      "RequestStatus\022*\n\013server_meta\030\002 \001(\0132\025.exe" +
+      "c.user.ServerMeta\022(\n\005error\030\003 \001(\0132\031.exec." +
+      "shared.DrillPBError\"\377\r\n\nServerMeta\022\035\n\025al" +
+      "l_tables_selectable\030\001 \001(\010\022%\n\035blob_includ" +
+      "ed_in_max_row_size\030\002 \001(\010\022\030\n\020catalog_at_s" +
+      "tart\030\003 \001(\010\022\031\n\021catalog_separator\030\004 \001(\t\022\024\n" +
+      "\014catalog_term\030\005 \001(\t\0222\n\017collate_support\030\006" +
+      " \003(\0162\031.exec.user.CollateSupport\022!\n\031colum",
+      "n_aliasing_supported\030\007 \001(\010\0222\n\017convert_su" +
+      "pport\030\010 \003(\0132\031.exec.user.ConvertSupport\022E" +
+      "\n\031correlation_names_support\030\t \001(\0162\".exec" +
+      ".user.CorrelationNamesSupport\022\033\n\023date_ti" +
+      "me_functions\030\n \003(\t\022F\n\032date_time_literals" +
+      "_support\030\013 \003(\0162\".exec.user.DateTimeLiter" +
+      "alsSupport\0223\n\020group_by_support\030\014 \001(\0162\031.e" +
+      "xec.user.GroupBySupport\0226\n\021identifier_ca" +
+      "sing\030\r \001(\0162\033.exec.user.IdentifierCasing\022" +
+      "\037\n\027identifier_quote_string\030\016 \001(\t\022$\n\034like",
+      "_escape_clause_supported\030\017 \001(\010\022!\n\031max_bi" +
+      "nary_literal_length\030\020 \001(\r\022\037\n\027max_catalog" +
+      "_name_length\030\021 \001(\r\022\037\n\027max_char_literal_l" +
+      "ength\030\022 \001(\r\022\036\n\026max_column_name_length\030\023 " +
+      "\001(\r\022\037\n\027max_columns_in_group_by\030\024 \001(\r\022\037\n\027" +
+      "max_columns_in_order_by\030\025 \001(\r\022\035\n\025max_col" +
+      "umns_in_select\030\026 \001(\r\022\036\n\026max_cursor_name_" +
+      "length\030\027 \001(\r\022\034\n\024max_logical_lob_size\030\030 \001" +
+      "(\r\022\024\n\014max_row_size\030\031 \001(\r\022\036\n\026max_schema_n" +
+      "ame_length\030\032 \001(\r\022\034\n\024max_statement_length",
+      "\030\033 \001(\r\022\026\n\016max_statements\030\034 \001(\r\022\035\n\025max_ta" +
+      "ble_name_length\030\035 \001(\r\022\034\n\024max_tables_in_s" +
+      "elect\030\036 \001(\r\022\034\n\024max_user_name_length\030\037 \001(" +
+      "\r\0220\n\016null_collation\030  \001(\0162\030.exec.user.Nu" +
+      "llCollation\022&\n\036null_plus_non_null_equals" +
+      "_null\030! \001(\010\022\031\n\021numeric_functions\030\" \003(\t\0223" +
+      "\n\020order_by_support\030# \003(\0162\031.exec.user.Ord" +
+      "erBySupport\0227\n\022outer_join_support\030$ \003(\0162" +
+      "\033.exec.user.OuterJoinSupport\022=\n\030quoted_i" +
+      "dentifier_casing\030% \001(\0162\033.exec.user.Ident",
+      "ifierCasing\022\021\n\tread_only\030& \001(\010\022\023\n\013schema" +
+      "_term\030\' \001(\t\022\034\n\024search_escape_string\030( \001(" +
+      "\t\022#\n\033select_for_update_supported\030) \001(\010\022\032" +
+      "\n\022special_characters\030* \001(\t\022\024\n\014sql_keywor" +
+      "ds\030+ \003(\t\022\030\n\020string_functions\030, \003(\t\0224\n\020su" +
+      "bquery_support\030- \003(\0162\032.exec.user.SubQuer" +
+      "ySupport\022\030\n\020system_functions\030. \003(\t\022\022\n\nta" +
+      "ble_term\030/ \001(\t\022\035\n\025transaction_supported\030" +
+      "0 \001(\010\022.\n\runion_support\0301 \003(\0162\027.exec.user" +
+      ".UnionSupport\"\353\001\n\010RunQuery\0221\n\014results_mo",
+      "de\030\001 \001(\0162\033.exec.user.QueryResultsMode\022$\n" +
+      "\004type\030\002 \001(\0162\026.exec.shared.QueryType\022\014\n\004p" +
+      "lan\030\003 \001(\t\0221\n\tfragments\030\004 \003(\0132\036.exec.bit." +
+      "control.PlanFragment\022E\n\031prepared_stateme" +
+      "nt_handle\030\005 \001(\0132\".exec.user.PreparedStat" +
+      "ementHandle*\320\003\n\007RpcType\022\r\n\tHANDSHAKE\020\000\022\007" +
+      "\n\003ACK\020\001\022\013\n\007GOODBYE\020\002\022\r\n\tRUN_QUERY\020\003\022\020\n\014C" +
+      "ANCEL_QUERY\020\004\022\023\n\017REQUEST_RESULTS\020\005\022\027\n\023RE" +
+      "SUME_PAUSED_QUERY\020\013\022\034\n\030GET_QUERY_PLAN_FR" +
+      "AGMENTS\020\014\022\020\n\014GET_CATALOGS\020\016\022\017\n\013GET_SCHEM",
+      "AS\020\017\022\016\n\nGET_TABLES\020\020\022\017\n\013GET_COLUMNS\020\021\022\035\n" +
+      "\031CREATE_PREPARED_STATEMENT\020\026\022\023\n\017GET_SERV" +
+      "ER_META\020\010\022\016\n\nQUERY_DATA\020\006\022\020\n\014QUERY_HANDL" +
+      "E\020\007\022\030\n\024QUERY_PLAN_FRAGMENTS\020\r\022\014\n\010CATALOG" +
+      "S\020\022\022\013\n\007SCHEMAS\020\023\022\n\n\006TABLES\020\024\022\013\n\007COLUMNS\020" +
+      "\025\022\026\n\022PREPARED_STATEMENT\020\027\022\017\n\013SERVER_META" +
+      "\020\t\022\020\n\014QUERY_RESULT\020\n\022\020\n\014SASL_MESSAGE\020\030*H" +
+      "\n\013SaslSupport\022\030\n\024UNKNOWN_SASL_SUPPORT\020\000\022" +
+      "\r\n\tSASL_AUTH\020\001\022\020\n\014SASL_PRIVACY\020\002*#\n\020Quer" +
+      "yResultsMode\022\017\n\013STREAM_FULL\020\001*q\n\017Handsha",
+      "keStatus\022\013\n\007SUCCESS\020\001\022\030\n\024RPC_VERSION_MIS" +
+      "MATCH\020\002\022\017\n\013AUTH_FAILED\020\003\022\023\n\017UNKNOWN_FAIL" +
+      "URE\020\004\022\021\n\rAUTH_REQUIRED\020\005*D\n\rRequestStatu" +
+      "s\022\022\n\016UNKNOWN_STATUS\020\000\022\006\n\002OK\020\001\022\n\n\006FAILED\020" +
+      "\002\022\013\n\007TIMEOUT\020\003*Y\n\023ColumnSearchability\022\031\n" +
+      "\025UNKNOWN_SEARCHABILITY\020\000\022\010\n\004NONE\020\001\022\010\n\004CH" +
+      "AR\020\002\022\n\n\006NUMBER\020\003\022\007\n\003ALL\020\004*K\n\022ColumnUpdat" +
+      "ability\022\030\n\024UNKNOWN_UPDATABILITY\020\000\022\r\n\tREA" +
+      "D_ONLY\020\001\022\014\n\010WRITABLE\020\002*1\n\016CollateSupport" +
+      "\022\016\n\nCS_UNKNOWN\020\000\022\017\n\013CS_GROUP_BY\020\001*J\n\027Cor",
+      "relationNamesSupport\022\013\n\007CN_NONE\020\001\022\026\n\022CN_" +
+      "DIFFERENT_NAMES\020\002\022\n\n\006CN_ANY\020\003*\271\003\n\027DateTi" +
+      "meLiteralsSupport\022\016\n\nDL_UNKNOWN\020\000\022\013\n\007DL_" +
+      "DATE\020\001\022\013\n\007DL_TIME\020\002\022\020\n\014DL_TIMESTAMP\020\003\022\024\n" +
+      "\020DL_INTERVAL_YEAR\020\004\022\025\n\021DL_INTERVAL_MONTH" +
+      "\020\005\022\023\n\017DL_INTERVAL_DAY\020\006\022\024\n\020DL_INTERVAL_H" +
+      "OUR\020\007\022\026\n\022DL_INTERVAL_MINUTE\020\010\022\026\n\022DL_INTE" +
+      "RVAL_SECOND\020\t\022\035\n\031DL_INTERVAL_YEAR_TO_MON" +
+      "TH\020\n\022\033\n\027DL_INTERVAL_DAY_TO_HOUR\020\013\022\035\n\031DL_" +
+      "INTERVAL_DAY_TO_MINUTE\020\014\022\035\n\031DL_INTERVAL_",
+      "DAY_TO_SECOND\020\r\022\036\n\032DL_INTERVAL_HOUR_TO_M" +
+      "INUTE\020\016\022\036\n\032DL_INTERVAL_HOUR_TO_SECOND\020\017\022" +
+      " \n\034DL_INTERVAL_MINUTE_TO_SECOND\020\020*Y\n\016Gro" +
+      "upBySupport\022\013\n\007GB_NONE\020\001\022\022\n\016GB_SELECT_ON" +
+      "LY\020\002\022\024\n\020GB_BEYOND_SELECT\020\003\022\020\n\014GB_UNRELAT" +
+      "ED\020\004*x\n\020IdentifierCasing\022\016\n\nIC_UNKNOWN\020\000" +
+      "\022\023\n\017IC_STORES_LOWER\020\001\022\023\n\017IC_STORES_MIXED" +
+      "\020\002\022\023\n\017IC_STORES_UPPER\020\003\022\025\n\021IC_SUPPORTS_M" +
+      "IXED\020\004*X\n\rNullCollation\022\016\n\nNC_UNKNOWN\020\000\022" +
+      "\017\n\013NC_AT_START\020\001\022\r\n\tNC_AT_END\020\002\022\013\n\007NC_HI",
+      "GH\020\003\022\n\n\006NC_LOW\020\004*E\n\016OrderBySupport\022\016\n\nOB" +
+      "_UNKNOWN\020\000\022\020\n\014OB_UNRELATED\020\001\022\021\n\rOB_EXPRE" +
+      "SSION\020\002*\226\001\n\020OuterJoinSupport\022\016\n\nOJ_UNKNO" +
+      "WN\020\000\022\013\n\007OJ_LEFT\020\001\022\014\n\010OJ_RIGHT\020\002\022\013\n\007OJ_FU" +
+      "LL\020\003\022\r\n\tOJ_NESTED\020\004\022\022\n\016OJ_NOT_ORDERED\020\005\022" +
+      "\014\n\010OJ_INNER\020\006\022\031\n\025OJ_ALL_COMPARISON_OPS\020\007" +
+      "*\204\001\n\017SubQuerySupport\022\016\n\nSQ_UNKNOWN\020\000\022\021\n\r" +
+      "SQ_CORRELATED\020\001\022\024\n\020SQ_IN_COMPARISON\020\002\022\020\n" +
+      "\014SQ_IN_EXISTS\020\003\022\020\n\014SQ_IN_INSERT\020\004\022\024\n\020SQ_" +
+      "IN_QUANTIFIED\020\005*;\n\014UnionSupport\022\r\n\tU_UNK",
+      "NOWN\020\000\022\013\n\007U_UNION\020\001\022\017\n\013U_UNION_ALL\020\002B+\n\033" +
+      "org.apache.drill.exec.protoB\nUserProtosH" +
+      "\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -41910,7 +42083,7 @@ public final class UserProtos {
           internal_static_exec_user_BitToUserHandshake_fieldAccessorTable = new
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_exec_user_BitToUserHandshake_descriptor,
-              new java.lang.String[] { "RpcVersion", "Status", "ErrorId", "ErrorMessage", "ServerInfos", "AuthenticationMechanisms", "SupportedMethods", });
+              new java.lang.String[] { "RpcVersion", "Status", "ErrorId", "ErrorMessage", "ServerInfos", "AuthenticationMechanisms", "SupportedMethods", "Encrypted", "MaxWrappedSize", });
           internal_static_exec_user_LikeFilter_descriptor =
             getDescriptor().getMessageTypes().get(8);
           internal_static_exec_user_LikeFilter_fieldAccessorTable = new

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java b/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
index 0cad1c0..c22519d 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/beans/BitToUserHandshake.java
@@ -56,6 +56,8 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
     private RpcEndpointInfos serverInfos;
     private List<String> authenticationMechanisms;
     private List<RpcType> supportedMethods;
+    private Boolean encrypted;
+    private int maxWrappedSize;
 
     public BitToUserHandshake()
     {
@@ -155,6 +157,32 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
         return this;
     }
 
+    // encrypted
+
+    public Boolean getEncrypted()
+    {
+        return encrypted;
+    }
+
+    public BitToUserHandshake setEncrypted(Boolean encrypted)
+    {
+        this.encrypted = encrypted;
+        return this;
+    }
+
+    // maxWrappedSize
+
+    public int getMaxWrappedSize()
+    {
+        return maxWrappedSize;
+    }
+
+    public BitToUserHandshake setMaxWrappedSize(int maxWrappedSize)
+    {
+        this.maxWrappedSize = maxWrappedSize;
+        return this;
+    }
+
     // java serialization
 
     public void readExternal(ObjectInput in) throws IOException
@@ -235,6 +263,12 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
                         message.supportedMethods = new ArrayList<RpcType>();
                     message.supportedMethods.add(RpcType.valueOf(input.readEnum()));
                     break;
+                case 9:
+                    message.encrypted = input.readBool();
+                    break;
+                case 10:
+                    message.maxWrappedSize = input.readInt32();
+                    break;
                 default:
                     input.handleUnknownField(number, this);
             }   
@@ -277,6 +311,12 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
                     output.writeEnum(8, supportedMethods.number, true);
             }
         }
+
+        if(message.encrypted != null)
+            output.writeBool(9, message.encrypted, false);
+
+        if(message.maxWrappedSize != 0)
+            output.writeInt32(10, message.maxWrappedSize, false);
     }
 
     public String getFieldName(int number)
@@ -290,6 +330,8 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
             case 6: return "serverInfos";
             case 7: return "authenticationMechanisms";
             case 8: return "supportedMethods";
+            case 9: return "encrypted";
+            case 10: return "maxWrappedSize";
             default: return null;
         }
     }
@@ -310,6 +352,8 @@ public final class BitToUserHandshake implements Externalizable, Message<BitToUs
         __fieldMap.put("serverInfos", 6);
         __fieldMap.put("authenticationMechanisms", 7);
         __fieldMap.put("supportedMethods", 8);
+        __fieldMap.put("encrypted", 9);
+        __fieldMap.put("maxWrappedSize", 10);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/protocol/src/main/java/org/apache/drill/exec/proto/beans/SaslSupport.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/beans/SaslSupport.java b/protocol/src/main/java/org/apache/drill/exec/proto/beans/SaslSupport.java
index 8a5aa73..8a668eb 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/beans/SaslSupport.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/beans/SaslSupport.java
@@ -23,7 +23,8 @@ package org.apache.drill.exec.proto.beans;
 public enum SaslSupport implements com.dyuproject.protostuff.EnumLite<SaslSupport>
 {
     UNKNOWN_SASL_SUPPORT(0),
-    SASL_AUTH(1);
+    SASL_AUTH(1),
+    SASL_PRIVACY(2);
     
     public final int number;
     
@@ -43,6 +44,7 @@ public enum SaslSupport implements com.dyuproject.protostuff.EnumLite<SaslSuppor
         {
             case 0: return UNKNOWN_SASL_SUPPORT;
             case 1: return SASL_AUTH;
+            case 2: return SASL_PRIVACY;
             default: return null;
         }
     }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/protocol/src/main/protobuf/User.proto
----------------------------------------------------------------------
diff --git a/protocol/src/main/protobuf/User.proto b/protocol/src/main/protobuf/User.proto
index 4b722b3..2af8b26 100644
--- a/protocol/src/main/protobuf/User.proto
+++ b/protocol/src/main/protobuf/User.proto
@@ -70,6 +70,7 @@ message RpcEndpointInfos {
 enum SaslSupport {
   UNKNOWN_SASL_SUPPORT = 0;
   SASL_AUTH = 1;
+  SASL_PRIVACY = 2;
 }
 
 message UserToBitHandshake {
@@ -124,6 +125,8 @@ message BitToUserHandshake {
   optional RpcEndpointInfos server_infos = 6;
   repeated string authenticationMechanisms = 7;
   repeated RpcType supported_methods = 8;
+  optional bool encrypted = 9;
+  optional int32 maxWrappedSize = 10;
 }
 
 /*


[3/6] drill git commit: DRILL-4335: Apache Drill should support network encryption.

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
index a7ea7b7..2f47538 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserClient.java
@@ -69,6 +69,7 @@ import org.apache.drill.exec.rpc.security.AuthenticationOutcomeListener;
 import org.apache.drill.exec.rpc.security.AuthenticatorFactory;
 import org.apache.drill.exec.rpc.security.ClientAuthenticatorProvider;
 import org.apache.drill.exec.rpc.security.plain.PlainFactory;
+import org.apache.drill.exec.rpc.security.SaslProperties;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.slf4j.Logger;
 
@@ -81,6 +82,7 @@ import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.SettableFuture;
 import com.google.protobuf.MessageLite;
 
+
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
@@ -137,18 +139,32 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
    */
   public void connect(final DrillbitEndpoint endpoint, final DrillProperties properties,
                       final UserCredentials credentials) throws RpcException {
-    final UserToBitHandshake handshake = UserToBitHandshake.newBuilder()
+    final UserToBitHandshake.Builder hsBuilder = UserToBitHandshake.newBuilder()
         .setRpcVersion(UserRpcConfig.RPC_VERSION)
         .setSupportListening(true)
         .setSupportComplexTypes(supportComplexTypes)
         .setSupportTimeout(true)
         .setCredentials(credentials)
         .setClientInfos(UserRpcUtils.getRpcEndpointInfos(clientName))
-        .setSaslSupport(SaslSupport.SASL_AUTH)
-        .setProperties(properties.serializeForServer())
-        .build();
+        .setSaslSupport(SaslSupport.SASL_PRIVACY)
+        .setProperties(properties.serializeForServer());
+
+    // Only used for testing purpose
+    if (properties.containsKey(DrillProperties.TEST_SASL_LEVEL)) {
+      hsBuilder.setSaslSupport(SaslSupport.valueOf(
+          Integer.parseInt(properties.getProperty(DrillProperties.TEST_SASL_LEVEL))));
+    }
+
+    connect(hsBuilder.build(), endpoint).checkedGet();
 
-    connect(handshake, endpoint).checkedGet();
+    // Check if client needs encryption and server is not configured for encryption.
+    final boolean clientNeedsEncryption = properties.containsKey(DrillProperties.SASL_ENCRYPT)
+        && Boolean.parseBoolean(properties.getProperty(DrillProperties.SASL_ENCRYPT));
+
+    if(clientNeedsEncryption && !connection.isEncryptionEnabled()) {
+      throw new NonTransientRpcException("Client needs encrypted connection but server is not configured for " +
+          "encryption. Please check connection parameter or contact your administrator");
+    }
 
     if (serverAuthMechanisms != null) {
       try {
@@ -192,6 +208,12 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
   private CheckedFuture<Void, SaslException> authenticate(final DrillProperties properties) {
     final Map<String, String> propertiesMap = properties.stringPropertiesAsMap();
 
+    // Set correct QOP property and Strength based on server needs encryption or not.
+    // If ChunkMode is enabled then negotiate for buffer size equal to wrapChunkSize,
+    // If ChunkMode is disabled then negotiate for MAX_WRAPPED_SIZE buffer size.
+    propertiesMap.putAll(SaslProperties.getSaslProperties(connection.isEncryptionEnabled(),
+                                                          connection.getMaxWrappedSize()));
+
     final SettableFuture<Void> authSettable = SettableFuture.create(); // use handleAuthFailure to setException
     final CheckedFuture<Void, SaslException> authFuture =
         new AbstractCheckedFuture<Void, SaslException>(authSettable) {
@@ -201,10 +223,12 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
             if (e instanceof ExecutionException) {
               final Throwable cause = Throwables.getRootCause(e);
               if (cause instanceof SaslException) {
-                return new SaslException("Authentication failed: " + cause.getMessage(), cause);
+                return new SaslException(String.format("Authentication failed. [Details: %s, Error %s]",
+                    connection.getEncryptionCtxtString(), cause.getMessage()), cause);
               }
             }
-            return new SaslException("Authentication failed unexpectedly.", e);
+            return new SaslException(String.format("Authentication failed unexpectedly. [Details: %s, Error %s]",
+                connection.getEncryptionCtxtString(), e.getMessage()), e);
           }
         };
 
@@ -215,11 +239,13 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
     try {
       factory = getAuthenticatorFactory(properties);
       mechanismName = factory.getSimpleName();
-      logger.trace("Will try to authenticate to server using {} mechanism.", mechanismName);
+      logger.trace("Will try to authenticate to server using {} mechanism with encryption context {}",
+          mechanismName, connection.getEncryptionCtxtString());
       ugi = factory.createAndLoginUser(propertiesMap);
       saslClient = factory.createSaslClient(ugi, propertiesMap);
       if (saslClient == null) {
-        throw new SaslException("Cannot initiate authentication. Insufficient credentials?");
+        throw new SaslException(String.format("Cannot initiate authentication using %s mechanism. Insufficient " +
+            "credentials or selected mechanism doesn't support configured security layers?", factory.getSimpleName()));
       }
       connection.setSaslClient(saslClient);
     } catch (final IOException e) {
@@ -255,13 +281,12 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
     // first, check if a certain mechanism must be used
     String authMechanism = properties.getProperty(DrillProperties.AUTH_MECHANISM);
     if (authMechanism != null) {
-      if (!ClientAuthenticatorProvider.getInstance()
-          .containsFactory(authMechanism)) {
+      if (!ClientAuthenticatorProvider.getInstance().containsFactory(authMechanism)) {
         throw new SaslException(String.format("Unknown mechanism: %s", authMechanism));
       }
       if (!mechanismSet.contains(authMechanism.toUpperCase())) {
-        throw new SaslException(String.format("Server does not support authentication using: %s",
-            authMechanism));
+        throw new SaslException(String.format("Server does not support authentication using: %s. [Details: %s]",
+            authMechanism, connection.getEncryptionCtxtString()));
       }
       return ClientAuthenticatorProvider.getInstance()
           .getAuthenticatorFactory(authMechanism);
@@ -282,8 +307,8 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
           .getAuthenticatorFactory(PlainFactory.SIMPLE_NAME);
     }
 
-    throw new SaslException(String.format("Server requires authentication using %s. Insufficient credentials?",
-        serverAuthMechanisms));
+    throw new SaslException(String.format("Server requires authentication using %s. Insufficient credentials?. " +
+        "[Details: %s]. ", serverAuthMechanisms, connection.getEncryptionCtxtString()));
   }
 
   protected <SEND extends MessageLite, RECEIVE extends MessageLite>
@@ -331,8 +356,8 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
     if (!authComplete) {
       // Remote should not be making any requests before authenticating, drop connection
       throw new RpcException(String.format("Request of type %d is not allowed without authentication. " +
-                  "Remote on %s must authenticate before making requests. Connection dropped.",
-              rpcType, connection.getRemoteAddress()));
+          "Remote on %s must authenticate before making requests. Connection dropped.",
+          rpcType, connection.getRemoteAddress()));
     }
     switch (rpcType) {
     case RpcType.QUERY_DATA_VALUE:
@@ -361,8 +386,14 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
       break;
     case AUTH_REQUIRED: {
       authComplete = false;
-      logger.trace("Server requires authentication before proceeding.");
       serverAuthMechanisms = ImmutableList.copyOf(inbound.getAuthenticationMechanismsList());
+      connection.setEncryption(inbound.hasEncrypted() && inbound.getEncrypted());
+
+      if (inbound.hasMaxWrappedSize()) {
+        connection.setMaxWrappedSize(inbound.getMaxWrappedSize());
+      }
+      logger.trace(String.format("Server requires authentication with encryption context %s before proceeding.",
+          connection.getEncryptionCtxtString()));
       break;
     }
     case AUTH_FAILED:
@@ -384,6 +415,9 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
   public class UserToBitConnection extends AbstractClientConnection {
 
     UserToBitConnection(SocketChannel channel) {
+
+      // by default connection is not set for encryption. After receiving handshake msg from server we set the
+      // isEncryptionEnabled, useChunkMode and chunkModeSize correctly.
       super(channel, "user client");
     }
 
@@ -396,6 +430,16 @@ public class UserClient extends BasicClient<RpcType, UserClient.UserToBitConnect
     protected Logger getLogger() {
       return logger;
     }
+
+    @Override
+    public void incConnectionCounter() {
+      // no-op
+    }
+
+    @Override
+    public void decConnectionCounter() {
+      // no-op
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserConnectionConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserConnectionConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserConnectionConfig.java
index 49a866b..64ac6be 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserConnectionConfig.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserConnectionConfig.java
@@ -17,11 +17,14 @@
  */
 package org.apache.drill.exec.rpc.user;
 
+import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.exception.DrillbitStartupException;
 import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.rpc.AbstractConnectionConfig;
 import org.apache.drill.exec.rpc.RequestHandler;
+import org.apache.drill.exec.rpc.RpcConstants;
+import org.apache.drill.exec.rpc.security.AuthenticatorProvider;
 import org.apache.drill.exec.server.BootStrapContext;
 
 // config for bit to user connection
@@ -35,24 +38,46 @@ class UserConnectionConfig extends AbstractConnectionConfig {
   private final UserServerRequestHandler handler;
 
   UserConnectionConfig(BufferAllocator allocator, BootStrapContext context, UserServerRequestHandler handler)
-      throws DrillbitStartupException {
+    throws DrillbitStartupException {
     super(allocator, context);
     this.handler = handler;
 
-    if (context.getConfig().getBoolean(ExecConstants.USER_AUTHENTICATION_ENABLED)) {
-      if (getAuthProvider().getAllFactoryNames().isEmpty()) {
+    final DrillConfig config = context.getConfig();
+    final AuthenticatorProvider authProvider = getAuthProvider();
+
+    if (config.getBoolean(ExecConstants.USER_AUTHENTICATION_ENABLED)) {
+      if (authProvider.getAllFactoryNames().isEmpty()) {
         throw new DrillbitStartupException("Authentication enabled, but no mechanisms found. Please check " +
             "authentication configuration.");
       }
       authEnabled = true;
-      logger.info("Configured all user connections to require authentication using: {}",
-          getAuthProvider().getAllFactoryNames());
+
+      // Update encryption related parameters.
+      encryptionContext.setEncryption(config.getBoolean(ExecConstants.USER_ENCRYPTION_SASL_ENABLED));
+      final int maxWrappedSize = config.getInt(ExecConstants.USER_ENCRYPTION_SASL_MAX_WRAPPED_SIZE);
+
+      if (maxWrappedSize <= 0) {
+        throw new DrillbitStartupException(String.format("Invalid value configured for " +
+            "user.encryption.sasl.max_wrapped_size. Must be a positive integer in bytes with a recommended max value " +
+            "of %s", RpcConstants.MAX_RECOMMENDED_WRAPPED_SIZE));
+      } else if (maxWrappedSize > RpcConstants.MAX_RECOMMENDED_WRAPPED_SIZE) {
+        logger.warn("The configured value of user.encryption.sasl.max_wrapped_size is too big. This may cause higher" +
+            " memory pressure. [Details: Recommended max value is %s]", RpcConstants.MAX_RECOMMENDED_WRAPPED_SIZE);
+      }
+      encryptionContext.setMaxWrappedSize(maxWrappedSize);
+
+      logger.info("Configured all user connections to require authentication with encryption: {} using: {}",
+          encryptionContext.getEncryptionCtxtString(), authProvider.getAllFactoryNames());
+    } else if (config.getBoolean(ExecConstants.USER_ENCRYPTION_SASL_ENABLED)) {
+      throw new DrillbitStartupException("Invalid security configuration. Encryption using SASL is enabled with " +
+          "authentication disabled. Please check the security.user configurations.");
     } else {
       authEnabled = false;
     }
 
-    impersonationManager = !context.getConfig().getBoolean(ExecConstants.IMPERSONATION_ENABLED) ? null :
-        new InboundImpersonationManager();
+    impersonationManager = !config.getBoolean(ExecConstants.IMPERSONATION_ENABLED)
+        ? null
+        : new InboundImpersonationManager();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcMetrics.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcMetrics.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcMetrics.java
new file mode 100644
index 0000000..ab93e3d
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserRpcMetrics.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc.user;
+
+import com.codahale.metrics.Counter;
+import org.apache.drill.exec.memory.BufferAllocator;
+import org.apache.drill.exec.metrics.DrillMetrics;
+import org.apache.drill.exec.rpc.AbstractRpcMetrics;
+import org.apache.drill.exec.rpc.RpcMetrics;
+
+/**
+ * Holds metrics related to bit user rpc layer
+ */
+class UserRpcMetrics extends AbstractRpcMetrics {
+  //private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(UserRpcMetrics.class);
+
+  // Total number of user client connection's to a DrillBit.
+  private static final Counter encryptedConnections = DrillMetrics.getRegistry()
+      .counter(CONNECTION_COUNTER_PREFIX + "user.encrypted");
+
+  private static final Counter unencryptedConnection = DrillMetrics.getRegistry()
+      .counter(CONNECTION_COUNTER_PREFIX + "user.unencrypted");
+
+  private static final RpcMetrics INSTANCE = new UserRpcMetrics();
+
+  // prevent instantiation
+  private UserRpcMetrics() {
+  }
+
+  public static RpcMetrics getInstance() {
+    return INSTANCE;
+  }
+
+  /**
+   * Should only be called when first access to getInstance is made. In this case inside {@link UserServer}.
+   * BitToUserConnection using the singleton instance should not call initialize.
+   *
+   * @param useEncryptedCounter
+   * @param allocator
+   */
+  @Override
+  public void initialize(boolean useEncryptedCounter, BufferAllocator allocator) {
+    this.useEncryptedCounter = useEncryptedCounter;
+    registerAllocatorMetrics(allocator);
+  }
+
+
+  @Override
+  public void addConnectionCount() {
+    if (useEncryptedCounter) {
+      encryptedConnections.inc();
+    } else {
+      unencryptedConnection.inc();
+    }
+  }
+
+  @Override
+  public void decConnectionCount() {
+    if (useEncryptedCounter) {
+      encryptedConnections.dec();
+    } else {
+      unencryptedConnection.dec();
+    }
+  }
+
+  private void registerAllocatorMetrics(final BufferAllocator allocator) {
+    registerAllocatorMetrics(allocator, ALLOCATOR_METRICS_PREFIX + "bit.user.");
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
index 9f0d502..543145f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserServer.java
@@ -44,6 +44,7 @@ import org.apache.drill.exec.rpc.BasicServer;
 import org.apache.drill.exec.rpc.OutOfMemoryHandler;
 import org.apache.drill.exec.rpc.OutboundRpcMessage;
 import org.apache.drill.exec.rpc.ProtobufLengthDecoder;
+import org.apache.drill.exec.rpc.RpcConstants;
 import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
 import org.apache.drill.exec.rpc.security.ServerAuthenticationHandler;
@@ -78,6 +79,9 @@ public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
         eventLoopGroup);
     this.config = new UserConnectionConfig(allocator, context, new UserServerRequestHandler(worker));
     this.userWorker = worker;
+
+    // Initialize Singleton instance of UserRpcMetrics.
+    ((UserRpcMetrics)UserRpcMetrics.getInstance()).initialize(config.isEncryptionEnabled(), allocator);
   }
 
   @Override
@@ -149,7 +153,7 @@ public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
     }
 
     void disableReadTimeout() {
-      getChannel().pipeline().remove(BasicServer.TIMEOUT_HANDLER);
+      getChannel().pipeline().remove(RpcConstants.TIMEOUT_HANDLER);
     }
 
     void setHandshake(final UserToBitHandshake inbound) {
@@ -186,6 +190,10 @@ public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
       if (config.getImpersonationManager() != null && targetName != null) {
         config.getImpersonationManager().replaceUserOnSession(targetName, session);
       }
+
+      // Increase the corresponding connection counter.
+      // For older clients we call this method directly.
+      incConnectionCounter();
     }
 
     @Override
@@ -237,6 +245,16 @@ public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
       cleanup();
       super.close();
     }
+
+    @Override
+    public void incConnectionCounter() {
+      UserRpcMetrics.getInstance().addConnectionCount();
+    }
+
+    @Override
+    public void decConnectionCounter() {
+      UserRpcMetrics.getInstance().decConnectionCount();
+    }
   }
 
   @Override
@@ -295,7 +313,16 @@ public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
           }
 
           final boolean clientSupportsSasl = inbound.hasSaslSupport() &&
-              (inbound.getSaslSupport().ordinal() >= SaslSupport.SASL_AUTH.ordinal());
+              (inbound.getSaslSupport().ordinal() > SaslSupport.UNKNOWN_SASL_SUPPORT.ordinal());
+
+          final int saslSupportOrdinal = (clientSupportsSasl) ? inbound.getSaslSupport().ordinal()
+                                                              : SaslSupport.UNKNOWN_SASL_SUPPORT.ordinal();
+
+          if (saslSupportOrdinal <= SaslSupport.SASL_AUTH.ordinal() && config.isEncryptionEnabled()) {
+            throw new UserAuthenticationException("The server doesn't allow client without encryption support." +
+                " Please upgrade your client or talk to your system administrator.");
+          }
+
           if (!clientSupportsSasl) { // for backward compatibility < 1.10
             final String userName = inbound.getCredentials().getUserName();
             if (logger.isTraceEnabled()) {
@@ -335,9 +362,14 @@ public class UserServer extends BasicServer<RpcType, BitToUserConnection> {
             }
           }
 
-          // mention server's authentication capabilities
+          // Offer all the configured mechanisms to client. If certain mechanism doesn't support encryption
+          // like PLAIN, those should fail during the SASL handshake negotiation.
           respBuilder.addAllAuthenticationMechanisms(config.getAuthProvider().getAllFactoryNames());
 
+          // set the encrypted flag in handshake message. For older clients this field is optional so will be ignored
+          respBuilder.setEncrypted(connection.isEncryptionEnabled());
+          respBuilder.setMaxWrappedSize(connection.getMaxWrappedSize());
+
           // for now, this means PLAIN credentials will be sent over twice
           // (during handshake and during sasl exchange)
           respBuilder.setStatus(HandshakeStatus.AUTH_REQUIRED);

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/security/UserAuthenticatorFactory.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/security/UserAuthenticatorFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/security/UserAuthenticatorFactory.java
index c7a1338..a79c1df 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/security/UserAuthenticatorFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/security/UserAuthenticatorFactory.java
@@ -46,6 +46,12 @@ public class UserAuthenticatorFactory {
    */
   public static UserAuthenticator createAuthenticator(final DrillConfig config, ScanResult scan)
       throws DrillbitStartupException {
+
+    if(!config.hasPath(USER_AUTHENTICATOR_IMPL)) {
+      throw new DrillbitStartupException(String.format("BOOT option '%s' is missing in config.",
+          USER_AUTHENTICATOR_IMPL));
+    }
+
     final String authImplConfigured = config.getString(USER_AUTHENTICATOR_IMPL);
 
     if (Strings.isNullOrEmpty(authImplConfigured)) {

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/DrillRoot.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/DrillRoot.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/DrillRoot.java
index ba0f212..84c471e 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/DrillRoot.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/DrillRoot.java
@@ -29,6 +29,8 @@ import javax.xml.bind.annotation.XmlRootElement;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.Sets;
+import org.apache.drill.common.config.DrillConfig;
+import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint;
 import org.apache.drill.exec.server.rest.DrillRestServer.UserAuthEnabled;
 import org.apache.drill.exec.work.WorkManager;
@@ -61,6 +63,10 @@ public class DrillRoot {
     final DrillbitEndpoint currentDrillbit = work.getContext().getEndpoint();
     final String currentVersion = currentDrillbit.getVersion();
 
+    final DrillConfig config = work.getContext().getConfig();
+    final boolean userEncryptionEnabled = config.getBoolean(ExecConstants.USER_ENCRYPTION_SASL_ENABLED);
+    final boolean bitEncryptionEnabled = config.getBoolean(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED);
+
     for (DrillbitEndpoint endpoint : work.getContext().getBits()) {
       final DrillbitInfo drillbit = new DrillbitInfo(endpoint,
               currentDrillbit.equals(endpoint),
@@ -71,7 +77,8 @@ public class DrillRoot {
       drillbits.add(drillbit);
     }
 
-    return new ClusterInfo(drillbits, currentVersion, mismatchedVersions);
+    return new ClusterInfo(drillbits, currentVersion, mismatchedVersions,
+      userEncryptionEnabled, bitEncryptionEnabled);
   }
 
   @XmlRootElement
@@ -79,14 +86,20 @@ public class DrillRoot {
     private final Collection<DrillbitInfo> drillbits;
     private final String currentVersion;
     private final Collection<String> mismatchedVersions;
+    private final boolean userEncryptionEnabled;
+    private final boolean bitEncryptionEnabled;
 
     @JsonCreator
     public ClusterInfo(Collection<DrillbitInfo> drillbits,
                        String currentVersion,
-                       Collection<String> mismatchedVersions) {
+                       Collection<String> mismatchedVersions,
+                       boolean userEncryption,
+                       boolean bitEncryption) {
       this.drillbits = Sets.newTreeSet(drillbits);
       this.currentVersion = currentVersion;
       this.mismatchedVersions = Sets.newTreeSet(mismatchedVersions);
+      this.userEncryptionEnabled = userEncryption;
+      this.bitEncryptionEnabled = bitEncryption;
     }
 
     public Collection<DrillbitInfo> getDrillbits() {
@@ -100,6 +113,10 @@ public class DrillRoot {
     public Collection<String> getMismatchedVersions() {
       return Sets.newTreeSet(mismatchedVersions);
     }
+
+    public boolean isUserEncryptionEnabled() { return userEncryptionEnabled; }
+
+    public boolean isBitEncryptionEnabled() { return bitEncryptionEnabled; }
   }
 
   public static class DrillbitInfo implements Comparable<DrillbitInfo> {

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/service/ServiceEngine.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/service/ServiceEngine.java b/exec/java-exec/src/main/java/org/apache/drill/exec/service/ServiceEngine.java
index 9fa3c27..07c54ef 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/service/ServiceEngine.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/service/ServiceEngine.java
@@ -18,6 +18,7 @@
 package org.apache.drill.exec.service;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
 import io.netty.buffer.PooledByteBufAllocatorL;
 import io.netty.channel.EventLoopGroup;
 
@@ -29,12 +30,10 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.drill.common.AutoCloseables;
-import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.common.util.DrillVersionInfo;
 import org.apache.drill.exec.ExecConstants;
 import org.apache.drill.exec.exception.DrillbitStartupException;
 import org.apache.drill.exec.memory.BufferAllocator;
-import org.apache.drill.exec.metrics.DrillMetrics;
 import org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint;
 import org.apache.drill.exec.rpc.TransportCheck;
 import org.apache.drill.exec.rpc.control.Controller;
@@ -44,8 +43,6 @@ import org.apache.drill.exec.rpc.user.UserServer;
 import org.apache.drill.exec.server.BootStrapContext;
 import org.apache.drill.exec.work.WorkManager;
 
-import com.codahale.metrics.Gauge;
-import com.codahale.metrics.MetricRegistry;
 import com.google.common.base.Stopwatch;
 
 public class ServiceEngine implements AutoCloseable {
@@ -84,53 +81,8 @@ public class ServiceEngine implements AutoCloseable {
     intialUserPort = context.getConfig().getInt(ExecConstants.INITIAL_USER_PORT);
     this.allowPortHunting = allowPortHunting;
     this.isDistributedMode = isDistributedMode;
-
-    registerMetrics(context.getMetrics());
   }
 
-  private void registerMetrics(final MetricRegistry registry) {
-    final String prefix = PooledByteBufAllocatorL.METRIC_PREFIX + "rpc.";
-    DrillMetrics.register(prefix + "user.used", new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return userAllocator.getAllocatedMemory();
-      }
-    });
-    DrillMetrics.register(prefix + "user.peak", new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return userAllocator.getPeakMemoryAllocation();
-      }
-    });
-    DrillMetrics.register(prefix + "bit.control.used", new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return controlAllocator.getAllocatedMemory();
-      }
-    });
-    DrillMetrics.register(prefix + "bit.control.peak", new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return controlAllocator.getPeakMemoryAllocation();
-      }
-    });
-
-    DrillMetrics.register(prefix + "bit.data.used", new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return dataAllocator.getAllocatedMemory();
-      }
-    });
-    DrillMetrics.register(prefix + "bit.data.peak", new Gauge<Long>() {
-      @Override
-      public Long getValue() {
-        return dataAllocator.getPeakMemoryAllocation();
-      }
-    });
-
-  }
-
-
   private static BufferAllocator newAllocator(
       BootStrapContext context, String name, String initReservation, String maxAllocation) {
     return context.getAllocator().newChildAllocator(

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/resources/drill-module.conf
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/resources/drill-module.conf b/exec/java-exec/src/main/resources/drill-module.conf
index 3d66d19..19e1b1f 100644
--- a/exec/java-exec/src/main/resources/drill-module.conf
+++ b/exec/java-exec/src/main/resources/drill-module.conf
@@ -152,6 +152,14 @@ drill.exec: {
     enabled: false
     use_login_principal: false
   }
+  security.user.encryption.sasl {
+    enabled : false,
+    max_wrapped_size : 65536
+  }
+  security.bit.encryption.sasl {
+    enabled : false,
+    max_wrapped_size : 65536
+  }
   trace: {
     directory: "/tmp/drill-trace",
     filesystem: "file:///"

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/resources/rest/index.ftl
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/resources/rest/index.ftl b/exec/java-exec/src/main/resources/rest/index.ftl
index 3175479..d1aa844 100644
--- a/exec/java-exec/src/main/resources/rest/index.ftl
+++ b/exec/java-exec/src/main/resources/rest/index.ftl
@@ -69,6 +69,27 @@
           </tbody>
         </table>
       </div>
+    </div>
+  </div>
+
+  <div class="row">
+      <div class="col-md-12">
+        <h3>Encryption Info <span class="label label-primary"></span></h3>
+        <div class="table-responsive">
+          <table class="table table-hover">
+            <tbody>
+                <tr>
+                  <td>Client to Bit Encryption:</td>
+                  <td>${model.isUserEncryptionEnabled()?string("enabled", "disabled")}</td>
+                </tr>
+                <tr>
+                  <td>Bit to Bit Encryption:</td>
+                  <td>${model.isBitEncryptionEnabled()?string("enabled", "disabled")}</td>
+                </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
   </div>
 </#macro>
 

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitBitKerberos.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitBitKerberos.java b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitBitKerberos.java
index c3cc2da..a3ea198 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitBitKerberos.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitBitKerberos.java
@@ -33,6 +33,7 @@ import org.apache.drill.common.scanner.persistence.ScanResult;
 import org.apache.drill.common.types.TypeProtos.MinorType;
 import org.apache.drill.common.types.Types;
 import org.apache.drill.exec.ExecConstants;
+import org.apache.drill.exec.exception.DrillbitStartupException;
 import org.apache.drill.exec.exception.FragmentSetupException;
 import org.apache.drill.exec.expr.TypeHelper;
 import org.apache.drill.exec.memory.BufferAllocator;
@@ -48,88 +49,45 @@ import org.apache.drill.exec.record.WritableBatch;
 import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
 import org.apache.drill.exec.rpc.control.WorkEventBus;
+import org.apache.drill.exec.rpc.security.KerberosHelper;
 import org.apache.drill.exec.server.BootStrapContext;
 import org.apache.drill.exec.vector.Float8Vector;
 import org.apache.drill.exec.vector.ValueVector;
 import org.apache.drill.exec.work.WorkManager.WorkerBee;
 import org.apache.drill.exec.work.fragment.FragmentManager;
-import org.apache.hadoop.security.UgiTestUtil;
 import org.apache.hadoop.security.authentication.util.KerberosName;
 import org.apache.hadoop.security.authentication.util.KerberosUtil;
-import org.apache.kerby.kerberos.kerb.KrbException;
-import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 
-import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Field;
-import java.net.ServerSocket;
-import java.nio.file.Files;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 
+import static junit.framework.TestCase.fail;
 import static org.junit.Assert.assertTrue;
 
 @Ignore("See DRILL-5387")
 public class TestBitBitKerberos extends BaseTestQuery {
-  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestBitBitKerberos.class);
+  //private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestBitBitKerberos.class);
 
+  private static KerberosHelper krbHelper;
   private static DrillConfig newConfig;
 
-  private static File workspace;
+  private static BootStrapContext c1;
+  private static FragmentManager manager;
+  private int port = 1234;
 
-  private static File kdcDir;
-  private static SimpleKdcServer kdc;
-  private static int kdcPort;
-
-  private static final String HOSTNAME = "localhost";
-  private static final String REALM = "EXAMPLE.COM";
-
-  private static final String SERVER_SHORT_NAME = System.getProperty("user.name");
-  private static final String SERVER_PRINCIPAL = SERVER_SHORT_NAME + "/" + HOSTNAME + "@" + REALM;
-
-  private static File keytabDir;
-  private static File serverKeytab;
-
-  private static boolean kdcStarted;
-
-  @SuppressWarnings("restriction")
   @BeforeClass
-  public static void setupKdc() throws Exception {
-    kdc = new SimpleKdcServer();
-    workspace = new File(getTempDir("kerberos_target"));
-
-    kdcDir = new File(workspace, TestBitBitKerberos.class.getSimpleName());
-    kdcDir.mkdirs();
-    kdc.setWorkDir(kdcDir);
-
-    kdc.setKdcHost(HOSTNAME);
-    kdcPort = getFreePort();
-    kdc.setAllowTcp(true);
-    kdc.setAllowUdp(false);
-    kdc.setKdcTcpPort(kdcPort);
-
-    logger.debug("Starting KDC server at {}:{}", HOSTNAME, kdcPort);
-
-    kdc.init();
-    kdc.start();
-    kdcStarted = true;
+  public static void setupTest() throws Exception {
 
     final Config config = DrillConfig.create(cloneDefaultTestConfigProperties());
-    keytabDir = new File(workspace, TestBitBitKerberos.class.getSimpleName() + "_keytabs");
-    keytabDir.mkdirs();
-    setupUsers(keytabDir);
-
-    // Kerby sets "java.security.krb5.conf" for us!
-    System.clearProperty("java.security.auth.login.config");
-    System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
-    // Uncomment the following lines for debugging.
-    // System.setProperty("sun.security.spnego.debug", "true");
-    // System.setProperty("sun.security.krb5.debug", "true");
+    krbHelper = new KerberosHelper(TestBitBitKerberos.class.getSimpleName());
+    krbHelper.setupKdc();
 
     newConfig = new DrillConfig(
         config.withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
@@ -141,9 +99,9 @@ public class TestBitBitKerberos extends BaseTestQuery {
         .withValue(ExecConstants.USE_LOGIN_PRINCIPAL,
             ConfigValueFactory.fromAnyRef(true))
         .withValue(BootStrapContext.SERVICE_PRINCIPAL,
-            ConfigValueFactory.fromAnyRef(SERVER_PRINCIPAL))
+            ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
         .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
-            ConfigValueFactory.fromAnyRef(serverKeytab.toString())),
+            ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString())),
         false);
 
     // Ignore the compile time warning caused by the code below.
@@ -159,65 +117,13 @@ public class TestBitBitKerberos extends BaseTestQuery {
     defaultRealm.set(null, KerberosUtil.getDefaultRealm());
 
     updateTestCluster(1, newConfig);
-  }
-
-  private static int getFreePort() throws IOException {
-    @SuppressWarnings("resource")
-    ServerSocket s = null;
-    try {
-      s = new ServerSocket(0);
-      s.setReuseAddress(true);
-      return s.getLocalPort();
-    } finally {
-      if (s != null) {
-        s.close();
-      }
-    }
-  }
-
-  private static void setupUsers(File keytabDir) throws KrbException {
-    // Create the server user
-    String serverPrincipal = SERVER_PRINCIPAL.substring(0, SERVER_PRINCIPAL.indexOf('@'));
-    serverKeytab = new File(keytabDir, serverPrincipal.replace('/', '_') + ".keytab");
-    logger.debug("Creating {} with keytab {}", SERVER_PRINCIPAL, serverKeytab);
-    setupUser(kdc, serverKeytab, SERVER_PRINCIPAL);
-  }
-
-  private static void setupUser(SimpleKdcServer kdc, File keytab, String principal)
-      throws KrbException {
-    kdc.createPrincipal(principal);
-    kdc.exportPrincipal(principal, keytab);
-  }
-
-  @AfterClass
-  public static void stopKdc() throws Exception {
-    if (kdcStarted) {
-      logger.info("Stopping KDC on {}", kdcPort);
-      kdc.stop();
-    }
-
-    deleteIfExists(serverKeytab);
-    deleteIfExists(keytabDir);
-    deleteIfExists(kdcDir);
-    deleteIfExists(workspace);
-    UgiTestUtil.resetUgi();
-  }
-
-  private static void deleteIfExists(File file) throws IOException {
-    if (file != null) {
-      Files.deleteIfExists(file.toPath());
-    }
-  }
-
-  @Test
-  public void success(@Injectable WorkerBee bee, @Injectable final WorkEventBus workBus) throws Exception {
 
     ScanResult result = ClassPathScanner.fromPrescan(newConfig);
-    @SuppressWarnings("resource")
-    final BootStrapContext c1 = new BootStrapContext(newConfig, result);
-    @SuppressWarnings({ "unused", "resource" })
-    final BootStrapContext c2 = new BootStrapContext(newConfig, result);
+    c1 = new BootStrapContext(newConfig, result);
+    setupFragmentContextAndManager();
+  }
 
+  private static void setupFragmentContextAndManager() {
     final FragmentContext fcontext = new MockUp<FragmentContext>(){
       @SuppressWarnings("unused")
       BufferAllocator getAllocator(){
@@ -225,7 +131,7 @@ public class TestBitBitKerberos extends BaseTestQuery {
       }
     }.getMockInstance();
 
-    final FragmentManager manager = new MockUp<FragmentManager>(){
+    manager = new MockUp<FragmentManager>(){
       int v = 0;
 
       @Mock
@@ -252,36 +158,6 @@ public class TestBitBitKerberos extends BaseTestQuery {
       }
 
     }.getMockInstance();
-
-
-    new NonStrictExpectations() {{
-      workBus.getFragmentManagerIfExists((FragmentHandle) any); result = manager;
-      workBus.getFragmentManager( (FragmentHandle) any); result = manager;
-    }};
-
-    int port = 1234;
-
-    DataConnectionConfig config = new DataConnectionConfig(c1.getAllocator(), c1,
-        new DataServerRequestHandler(workBus, bee));
-    @SuppressWarnings("resource")
-    DataServer server = new DataServer(config);
-
-    port = server.bind(port, true);
-    DrillbitEndpoint ep = DrillbitEndpoint.newBuilder().setAddress("localhost").setDataPort(port).build();
-    @SuppressWarnings("resource")
-    DataConnectionManager connectionManager = new DataConnectionManager(ep, config);
-    DataTunnel tunnel = new DataTunnel(connectionManager);
-    AtomicLong max = new AtomicLong(0);
-    for (int i = 0; i < 40; i++) {
-      long t1 = System.currentTimeMillis();
-      tunnel.sendRecordBatch(new TimingOutcome(max), new FragmentWritableBatch(false, QueryId.getDefaultInstance(), 1,
-          1, 1, 1, getRandomBatch(c1.getAllocator(), 5000)));
-      System.out.println(System.currentTimeMillis() - t1);
-      // System.out.println("sent.");
-    }
-    System.out.println(String.format("Max time: %d", max.get()));
-    assertTrue(max.get() > 2700);
-    Thread.sleep(5000);
   }
 
   private static WritableBatch getRandomBatch(BufferAllocator allocator, int records) {
@@ -289,8 +165,8 @@ public class TestBitBitKerberos extends BaseTestQuery {
     for (int i = 0; i < 5; i++) {
       @SuppressWarnings("resource")
       Float8Vector v = (Float8Vector) TypeHelper.getNewVector(
-          MaterializedField.create("a", Types.required(MinorType.FLOAT8)),
-          allocator);
+        MaterializedField.create("a", Types.required(MinorType.FLOAT8)),
+        allocator);
       v.allocateNew(records);
       v.getMutator().generateTestData(records);
       vectors.add(v);
@@ -302,7 +178,7 @@ public class TestBitBitKerberos extends BaseTestQuery {
     private AtomicLong max;
     private Stopwatch watch = Stopwatch.createStarted();
 
-    public TimingOutcome(AtomicLong max) {
+    TimingOutcome(AtomicLong max) {
       super();
       this.max = max;
     }
@@ -315,7 +191,8 @@ public class TestBitBitKerberos extends BaseTestQuery {
     @Override
     public void success(Ack value, ByteBuf buffer) {
       long micros = watch.elapsed(TimeUnit.MILLISECONDS);
-      System.out.println(String.format("Total time to send: %d, start time %d", micros, System.currentTimeMillis() - micros));
+      System.out.println(String.format("Total time to send: %d, start time %d", micros,
+          System.currentTimeMillis() - micros));
       while (true) {
         long nowMax = max.get();
         if (nowMax < micros) {
@@ -333,4 +210,161 @@ public class TestBitBitKerberos extends BaseTestQuery {
       // TODO(We don't have any interrupts in test code)
     }
   }
+
+  @Test
+  public void success(@Injectable WorkerBee bee, @Injectable final WorkEventBus workBus) throws Exception {
+
+    new NonStrictExpectations() {{
+      workBus.getFragmentManagerIfExists((FragmentHandle) any); result = manager;
+      workBus.getFragmentManager( (FragmentHandle) any); result = manager;
+    }};
+
+    DataConnectionConfig config = new DataConnectionConfig(c1.getAllocator(), c1,
+        new DataServerRequestHandler(workBus, bee));
+    DataServer server = new DataServer(config);
+
+    port = server.bind(port, true);
+    DrillbitEndpoint ep = DrillbitEndpoint.newBuilder().setAddress("localhost").setDataPort(port).build();
+    DataConnectionManager connectionManager = new DataConnectionManager(ep, config);
+    DataTunnel tunnel = new DataTunnel(connectionManager);
+    AtomicLong max = new AtomicLong(0);
+    for (int i = 0; i < 40; i++) {
+      long t1 = System.currentTimeMillis();
+      tunnel.sendRecordBatch(new TimingOutcome(max), new FragmentWritableBatch(false, QueryId.getDefaultInstance(), 1,
+          1, 1, 1, getRandomBatch(c1.getAllocator(), 5000)));
+      System.out.println(System.currentTimeMillis() - t1);
+      // System.out.println("sent.");
+    }
+    System.out.println(String.format("Max time: %d", max.get()));
+    assertTrue(max.get() > 2700);
+    Thread.sleep(5000);
+  }
+
+  @Test
+  public void successEncryption(@Injectable WorkerBee bee, @Injectable final WorkEventBus workBus) throws Exception {
+
+    newConfig = new DrillConfig(
+      config.withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("kerberos")))
+        .withValue(ExecConstants.BIT_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.BIT_AUTHENTICATION_MECHANISM,
+          ConfigValueFactory.fromAnyRef("kerberos"))
+        .withValue(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USE_LOGIN_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString())),
+      false);
+
+    updateTestCluster(1, newConfig);
+
+    new NonStrictExpectations() {{
+      workBus.getFragmentManagerIfExists((FragmentHandle) any); result = manager;
+      workBus.getFragmentManager( (FragmentHandle) any); result = manager;
+    }};
+
+    DataConnectionConfig config = new DataConnectionConfig(c1.getAllocator(), c1,
+      new DataServerRequestHandler(workBus, bee));
+    DataServer server = new DataServer(config);
+
+    port = server.bind(port, true);
+    DrillbitEndpoint ep = DrillbitEndpoint.newBuilder().setAddress("localhost").setDataPort(port).build();
+    DataConnectionManager connectionManager = new DataConnectionManager(ep, config);
+    DataTunnel tunnel = new DataTunnel(connectionManager);
+    AtomicLong max = new AtomicLong(0);
+    for (int i = 0; i < 40; i++) {
+      long t1 = System.currentTimeMillis();
+      tunnel.sendRecordBatch(new TimingOutcome(max), new FragmentWritableBatch(false, QueryId.getDefaultInstance(), 1,
+        1, 1, 1, getRandomBatch(c1.getAllocator(), 5000)));
+      System.out.println(System.currentTimeMillis() - t1);
+    }
+    System.out.println(String.format("Max time: %d", max.get()));
+    assertTrue(max.get() > 2700);
+    Thread.sleep(5000);
+  }
+
+  @Test
+  public void successEncryptionChunkMode(@Injectable WorkerBee bee, @Injectable final WorkEventBus workBus)
+    throws Exception {
+    newConfig = new DrillConfig(
+      config.withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("kerberos")))
+        .withValue(ExecConstants.BIT_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.BIT_AUTHENTICATION_MECHANISM,
+          ConfigValueFactory.fromAnyRef("kerberos"))
+        .withValue(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.BIT_ENCRYPTION_SASL_MAX_WRAPPED_SIZE,
+          ConfigValueFactory.fromAnyRef(100000))
+        .withValue(ExecConstants.USE_LOGIN_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString())),
+      false);
+
+    updateTestCluster(1, newConfig);
+
+    new NonStrictExpectations() {{
+      workBus.getFragmentManagerIfExists((FragmentHandle) any); result = manager;
+      workBus.getFragmentManager( (FragmentHandle) any); result = manager;
+    }};
+
+    DataConnectionConfig config = new DataConnectionConfig(c1.getAllocator(), c1,
+      new DataServerRequestHandler(workBus, bee));
+    DataServer server = new DataServer(config);
+
+    port = server.bind(port, true);
+    DrillbitEndpoint ep = DrillbitEndpoint.newBuilder().setAddress("localhost").setDataPort(port).build();
+    DataConnectionManager connectionManager = new DataConnectionManager(ep, config);
+    DataTunnel tunnel = new DataTunnel(connectionManager);
+    AtomicLong max = new AtomicLong(0);
+    for (int i = 0; i < 40; i++) {
+      long t1 = System.currentTimeMillis();
+      tunnel.sendRecordBatch(new TimingOutcome(max), new FragmentWritableBatch(false, QueryId.getDefaultInstance(), 1,
+        1, 1, 1, getRandomBatch(c1.getAllocator(), 5000)));
+      System.out.println(System.currentTimeMillis() - t1);
+    }
+    System.out.println(String.format("Max time: %d", max.get()));
+    assertTrue(max.get() > 2700);
+    Thread.sleep(5000);
+  }
+
+  @Test
+  public void failureEncryptionOnlyPlainMechanism() throws Exception {
+    try{
+      newConfig = new DrillConfig(
+        config.withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+          ConfigValueFactory.fromIterable(Lists.newArrayList("plain")))
+          .withValue(ExecConstants.BIT_AUTHENTICATION_ENABLED,
+            ConfigValueFactory.fromAnyRef(true))
+          .withValue(ExecConstants.BIT_AUTHENTICATION_MECHANISM,
+            ConfigValueFactory.fromAnyRef("kerberos"))
+          .withValue(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED,
+            ConfigValueFactory.fromAnyRef(true))
+          .withValue(ExecConstants.USE_LOGIN_PRINCIPAL,
+            ConfigValueFactory.fromAnyRef(true))
+          .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+            ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+          .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+            ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString())),
+        false);
+
+      updateTestCluster(1, newConfig);
+      fail();
+    } catch(Exception ex) {
+      assertTrue(ex.getCause() instanceof DrillbitStartupException);
+    }
+  }
+
+  @AfterClass
+  public static void cleanTest() throws Exception {
+    krbHelper.stopKdc();
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitRpc.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitRpc.java b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitRpc.java
index b3c15bd..bdc3230 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitRpc.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/data/TestBitRpc.java
@@ -17,19 +17,13 @@
  */
 package org.apache.drill.exec.rpc.data;
 
-import static org.junit.Assert.assertTrue;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Lists;
 import io.netty.buffer.ByteBuf;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
 import mockit.Injectable;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.NonStrictExpectations;
-
 import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.common.scanner.ClassPathScanner;
 import org.apache.drill.common.types.TypeProtos.MinorType;
@@ -57,8 +51,12 @@ import org.apache.drill.exec.work.WorkManager.WorkerBee;
 import org.apache.drill.exec.work.fragment.FragmentManager;
 import org.junit.Test;
 
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.junit.Assert.assertTrue;
 
 public class TestBitRpc extends ExecTest {
   static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestBitRpc.class);

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/security/KerberosHelper.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/security/KerberosHelper.java b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/security/KerberosHelper.java
new file mode 100644
index 0000000..3320cef
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/security/KerberosHelper.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc.security;
+
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.file.Files;
+
+import static org.apache.drill.exec.ExecTest.getTempDir;
+
+public class KerberosHelper {
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(KerberosHelper.class);
+
+  public File workspace;
+
+  private File kdcDir;
+  private SimpleKdcServer kdc;
+  private int kdcPort;
+
+  private final String HOSTNAME = "localhost";
+
+  public final String CLIENT_SHORT_NAME = "testUser";
+  public final String CLIENT_PRINCIPAL;
+
+  public String SERVER_PRINCIPAL;
+  private final String testName;
+
+  private File keytabDir;
+  public File clientKeytab;
+  public File serverKeytab;
+
+  private boolean kdcStarted;
+
+  public KerberosHelper(final String testName) {
+    final String realm = "EXAMPLE.COM";
+    CLIENT_PRINCIPAL = CLIENT_SHORT_NAME + "@" + realm;
+    final String serverShortName = System.getProperty("user.name");
+    SERVER_PRINCIPAL = serverShortName + "/" + HOSTNAME + "@" + realm;
+    this.testName = testName;
+  }
+
+  public void setupKdc() throws Exception {
+    kdc = new SimpleKdcServer();
+    workspace = new File(getTempDir("kerberos_target"));
+
+    kdcDir = new File(workspace, testName);
+    if(!kdcDir.mkdirs()) {
+      throw new Exception(String.format("Failed to create the kdc directory %s", kdcDir.getName()));
+    }
+    kdc.setWorkDir(kdcDir);
+
+    kdc.setKdcHost(HOSTNAME);
+    kdcPort = getFreePort();
+    kdc.setAllowTcp(true);
+    kdc.setAllowUdp(false);
+    kdc.setKdcTcpPort(kdcPort);
+
+    logger.debug("Starting KDC server at {}:{}", HOSTNAME, kdcPort);
+
+    kdc.init();
+    kdc.start();
+    kdcStarted = true;
+
+
+    keytabDir = new File(workspace, testName + "_keytabs");
+    if(!keytabDir.mkdirs()) {
+      throw new Exception(String.format("Failed to create the keytab directory %s", keytabDir.getName()));
+    }
+    setupUsers(keytabDir);
+
+    // Kerby sets "java.security.krb5.conf" for us!
+    System.clearProperty("java.security.auth.login.config");
+    System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+    // Uncomment the following lines for debugging.
+    // System.setProperty("sun.security.spnego.debug", "true");
+    // System.setProperty("sun.security.krb5.debug", "true");
+  }
+
+  private int getFreePort() throws IOException {
+    ServerSocket s = null;
+    try {
+      s = new ServerSocket(0);
+      s.setReuseAddress(true);
+      return s.getLocalPort();
+    } finally {
+      if (s != null) {
+        s.close();
+      }
+    }
+  }
+
+  private void setupUsers(File keytabDir) throws KrbException {
+    // Create the client user
+    String clientPrincipal = CLIENT_PRINCIPAL.substring(0, CLIENT_PRINCIPAL.indexOf('@'));
+    clientKeytab = new File(keytabDir, clientPrincipal.replace('/', '_') + ".keytab");
+    logger.debug("Creating {} with keytab {}", clientPrincipal, clientKeytab);
+    setupUser(kdc, clientKeytab, clientPrincipal);
+
+    // Create the server user
+    String serverPrincipal = SERVER_PRINCIPAL.substring(0, SERVER_PRINCIPAL.indexOf('@'));
+    serverKeytab = new File(keytabDir, serverPrincipal.replace('/', '_') + ".keytab");
+    logger.debug("Creating {} with keytab {}", SERVER_PRINCIPAL, serverKeytab);
+    setupUser(kdc, serverKeytab, SERVER_PRINCIPAL);
+  }
+
+  private void setupUser(SimpleKdcServer kdc, File keytab, String principal)
+    throws KrbException {
+    kdc.createPrincipal(principal);
+    kdc.exportPrincipal(principal, keytab);
+  }
+
+  public void stopKdc() throws Exception {
+    if (kdcStarted) {
+      logger.info("Stopping KDC on {}", kdcPort);
+      kdc.stop();
+    }
+
+    deleteIfExists(clientKeytab);
+    deleteIfExists(serverKeytab);
+    deleteIfExists(keytabDir);
+    deleteIfExists(kdcDir);
+    deleteIfExists(workspace);
+  }
+
+  private void deleteIfExists(File file) throws IOException {
+    if (file != null) {
+      Files.deleteIfExists(file.toPath());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberos.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberos.java b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberos.java
index 177268c..3fad005 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberos.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberos.java
@@ -23,99 +23,48 @@ import org.apache.drill.BaseTestQuery;
 import org.apache.drill.common.config.DrillProperties;
 import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.exec.ExecConstants;
+import org.apache.drill.exec.rpc.security.KerberosHelper;
 import org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl;
 import org.apache.drill.exec.server.BootStrapContext;
-import org.apache.hadoop.security.UgiTestUtil;
 import org.apache.hadoop.security.authentication.util.KerberosName;
 import org.apache.hadoop.security.authentication.util.KerberosUtil;
-import org.apache.kerby.kerberos.kerb.KrbException;
 import org.apache.kerby.kerberos.kerb.client.JaasKrbUtil;
-import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
 
 import javax.security.auth.Subject;
-import java.io.File;
-import java.io.IOException;
 import java.lang.reflect.Field;
-import java.net.ServerSocket;
-import java.nio.file.Files;
 import java.security.PrivilegedExceptionAction;
 import java.util.Properties;
 
 @Ignore("See DRILL-5387")
 public class TestUserBitKerberos extends BaseTestQuery {
-  private static final org.slf4j.Logger logger =
-      org.slf4j.LoggerFactory.getLogger(TestUserBitKerberos.class);
+  //private static final org.slf4j.Logger logger =org.slf4j.LoggerFactory.getLogger(TestUserBitKerberos.class);
 
-  private static File workspace;
-
-  private static File kdcDir;
-  private static SimpleKdcServer kdc;
-  private static int kdcPort;
-
-  private static final String HOSTNAME = "localhost";
-  private static final String REALM = "EXAMPLE.COM";
-
-  private static final String CLIENT_SHORT_NAME = "testUser";
-  private static final String CLIENT_PRINCIPAL = CLIENT_SHORT_NAME + "@" + REALM;
-  private static final String SERVER_SHORT_NAME = System.getProperty("user.name");
-  private static final String SERVER_PRINCIPAL = SERVER_SHORT_NAME + "/" + HOSTNAME + "@" + REALM;
-
-  private static File keytabDir;
-  private static File clientKeytab;
-  private static File serverKeytab;
-
-  private static boolean kdcStarted;
+  private static KerberosHelper krbHelper;
 
   @BeforeClass
-  public static void setupKdc() throws Exception {
-    kdc = new SimpleKdcServer();
-    workspace = new File(getTempDir("kerberos_target"));
-
-    kdcDir = new File(workspace, TestUserBitKerberos.class.getSimpleName());
-    kdcDir.mkdirs();
-    kdc.setWorkDir(kdcDir);
-
-    kdc.setKdcHost(HOSTNAME);
-    kdcPort = getFreePort();
-    kdc.setAllowTcp(true);
-    kdc.setAllowUdp(false);
-    kdc.setKdcTcpPort(kdcPort);
+  public static void setupTest() throws Exception {
 
-    logger.debug("Starting KDC server at {}:{}", HOSTNAME, kdcPort);
-
-    kdc.init();
-    kdc.start();
-    kdcStarted = true;
-
-
-    keytabDir = new File(workspace, TestUserBitKerberos.class.getSimpleName()
-        + "_keytabs");
-    keytabDir.mkdirs();
-    setupUsers(keytabDir);
-
-    // Kerby sets "java.security.krb5.conf" for us!
-    System.clearProperty("java.security.auth.login.config");
-    System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
-    // Uncomment the following lines for debugging.
-    // System.setProperty("sun.security.spnego.debug", "true");
-    // System.setProperty("sun.security.krb5.debug", "true");
+    krbHelper = new KerberosHelper(TestUserBitKerberos.class.getSimpleName());
+    krbHelper.setupKdc();
 
+    // Create a new DrillConfig which has user authentication enabled and authenticator set to
+    // UserAuthenticatorTestImpl.
     final DrillConfig newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
-        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
-            ConfigValueFactory.fromAnyRef(true))
-        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
-            ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
-        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
-            ConfigValueFactory.fromAnyRef(SERVER_PRINCIPAL))
-        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
-            ConfigValueFactory.fromAnyRef(serverKeytab.toString()))
-        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
-            ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos"))),
-        false);
+      .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+        ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+      .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+      .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+        ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+      .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos"))),
+      false);
 
     final Properties connectionProps = new Properties();
     connectionProps.setProperty(DrillProperties.USER, "anonymous");
@@ -136,66 +85,12 @@ public class TestUserBitKerberos extends BaseTestQuery {
     updateTestCluster(1, newConfig, connectionProps);
   }
 
-  private static int getFreePort() throws IOException {
-    ServerSocket s = null;
-    try {
-      s = new ServerSocket(0);
-      s.setReuseAddress(true);
-      return s.getLocalPort();
-    } finally {
-      if (s != null) {
-        s.close();
-      }
-    }
-  }
-
-  private static void setupUsers(File keytabDir) throws KrbException {
-    // Create the client user
-    String clientPrincipal = CLIENT_PRINCIPAL.substring(0, CLIENT_PRINCIPAL.indexOf('@'));
-    clientKeytab = new File(keytabDir, clientPrincipal.replace('/', '_') + ".keytab");
-    logger.debug("Creating {} with keytab {}", clientPrincipal, clientKeytab);
-    setupUser(kdc, clientKeytab, clientPrincipal);
-
-    // Create the server user
-    String serverPrincipal = SERVER_PRINCIPAL.substring(0, SERVER_PRINCIPAL.indexOf('@'));
-    serverKeytab = new File(keytabDir, serverPrincipal.replace('/', '_') + ".keytab");
-    logger.debug("Creating {} with keytab {}", SERVER_PRINCIPAL, serverKeytab);
-    setupUser(kdc, serverKeytab, SERVER_PRINCIPAL);
-  }
-
-  private static void setupUser(SimpleKdcServer kdc, File keytab, String principal)
-      throws KrbException {
-    kdc.createPrincipal(principal);
-    kdc.exportPrincipal(principal, keytab);
-  }
-
-  @AfterClass
-  public static void stopKdc() throws Exception {
-    if (kdcStarted) {
-      logger.info("Stopping KDC on {}", kdcPort);
-      kdc.stop();
-    }
-
-    deleteIfExists(clientKeytab);
-    deleteIfExists(serverKeytab);
-    deleteIfExists(keytabDir);
-    deleteIfExists(kdcDir);
-    deleteIfExists(workspace);
-    UgiTestUtil.resetUgi();
-  }
-
-  private static void deleteIfExists(File file) throws IOException {
-    if (file != null) {
-      Files.deleteIfExists(file.toPath());
-    }
-  }
-
   @Test
   public void successKeytab() throws Exception {
     final Properties connectionProps = new Properties();
-    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, SERVER_PRINCIPAL);
-    connectionProps.setProperty(DrillProperties.USER, CLIENT_PRINCIPAL);
-    connectionProps.setProperty(DrillProperties.KEYTAB, clientKeytab.getAbsolutePath());
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
     updateClient(connectionProps);
 
     // Run few queries using the new client
@@ -203,7 +98,7 @@ public class TestUserBitKerberos extends BaseTestQuery {
         .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
         .unOrdered()
         .baselineColumns("session_user")
-        .baselineValues(CLIENT_SHORT_NAME)
+        .baselineValues(krbHelper.CLIENT_SHORT_NAME)
         .go();
     test("SHOW SCHEMAS");
     test("USE INFORMATION_SCHEMA");
@@ -215,9 +110,10 @@ public class TestUserBitKerberos extends BaseTestQuery {
   @Test
   public void successTicket() throws Exception {
     final Properties connectionProps = new Properties();
-    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
     connectionProps.setProperty(DrillProperties.KERBEROS_FROM_SUBJECT, "true");
-    final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(CLIENT_PRINCIPAL, clientKeytab.getAbsoluteFile());
+    final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(krbHelper.CLIENT_PRINCIPAL,
+      krbHelper.clientKeytab.getAbsoluteFile());
 
     Subject.doAs(clientSubject, new PrivilegedExceptionAction<Void>() {
       @Override
@@ -232,7 +128,7 @@ public class TestUserBitKerberos extends BaseTestQuery {
         .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
         .unOrdered()
         .baselineColumns("session_user")
-        .baselineValues(CLIENT_SHORT_NAME)
+        .baselineValues(krbHelper.CLIENT_SHORT_NAME)
         .go();
     test("SHOW SCHEMAS");
     test("USE INFORMATION_SCHEMA");
@@ -240,4 +136,9 @@ public class TestUserBitKerberos extends BaseTestQuery {
     test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
     test("SELECT * FROM cp.`region.json` LIMIT 5");
   }
+
+  @AfterClass
+  public static void cleanTest() throws Exception {
+    krbHelper.stopKdc();
+  }
 }


[2/6] drill git commit: DRILL-4335: Apache Drill should support network encryption.

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberosEncryption.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberosEncryption.java b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberosEncryption.java
new file mode 100644
index 0000000..b9dd705
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/rpc/user/security/TestUserBitKerberosEncryption.java
@@ -0,0 +1,539 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc.user.security;
+
+import com.google.common.collect.Lists;
+import com.typesafe.config.ConfigValueFactory;
+import org.apache.drill.BaseTestQuery;
+import org.apache.drill.common.config.DrillConfig;
+import org.apache.drill.common.config.DrillProperties;
+import org.apache.drill.exec.ExecConstants;
+import org.apache.drill.exec.rpc.NonTransientRpcException;
+import org.apache.drill.exec.rpc.RpcException;
+import org.apache.drill.exec.rpc.security.KerberosHelper;
+import org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl;
+import org.apache.drill.exec.server.BootStrapContext;
+import org.apache.hadoop.security.authentication.util.KerberosName;
+import org.apache.hadoop.security.authentication.util.KerberosUtil;
+import org.apache.kerby.kerberos.kerb.client.JaasKrbUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import javax.security.auth.Subject;
+import java.lang.reflect.Field;
+import java.security.PrivilegedExceptionAction;
+import java.util.Properties;
+
+import static junit.framework.TestCase.fail;
+
+@Ignore("See DRILL-5387")
+public class TestUserBitKerberosEncryption extends BaseTestQuery {
+  private static final org.slf4j.Logger logger =
+      org.slf4j.LoggerFactory.getLogger(TestUserBitKerberosEncryption.class);
+
+  private static KerberosHelper krbHelper;
+  private static DrillConfig newConfig;
+
+  @BeforeClass
+  public static void setupTest() throws Exception {
+    krbHelper = new KerberosHelper(TestUserBitKerberosEncryption.class.getSimpleName());
+    krbHelper.setupKdc();
+
+    // Create a new DrillConfig which has user authentication enabled and authenticator set to
+    // UserAuthenticatorTestImpl.
+    newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+            ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+            ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+            ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+            ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+            ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+        .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+            ConfigValueFactory.fromAnyRef(true)),
+      false);
+
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+
+    // Ignore the compile time warning caused by the code below.
+
+    // Config is statically initialized at this point. But the above configuration results in a different
+    // initialization which causes the tests to fail. So the following two changes are required.
+
+    // (1) Refresh Kerberos config.
+    sun.security.krb5.Config.refresh();
+    // (2) Reset the default realm.
+    final Field defaultRealm = KerberosName.class.getDeclaredField("defaultRealm");
+    defaultRealm.setAccessible(true);
+    defaultRealm.set(null, KerberosUtil.getDefaultRealm());
+
+    // Start a secure cluster with client using Kerberos related parameters.
+    updateTestCluster(1, newConfig, connectionProps);
+  }
+
+  @AfterClass
+  public static void cleanTest() throws Exception {
+    krbHelper.stopKdc();
+  }
+
+  @Test
+  public void successKeytabWithoutChunking() throws Exception {
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+    updateClient(connectionProps);
+
+    // Run few queries using the new client
+    testBuilder()
+        .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
+        .unOrdered()
+        .baselineColumns("session_user")
+        .baselineValues(krbHelper.CLIENT_SHORT_NAME)
+        .go();
+    test("SHOW SCHEMAS");
+    test("USE INFORMATION_SCHEMA");
+    test("SHOW TABLES");
+    test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
+    test("SELECT * FROM cp.`region.json`");
+  }
+
+  @Test
+  public void successTicketWithoutChunking() throws Exception {
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KERBEROS_FROM_SUBJECT, "true");
+    final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(krbHelper.CLIENT_PRINCIPAL,
+                                                               krbHelper.clientKeytab.getAbsoluteFile());
+
+    Subject.doAs(clientSubject, new PrivilegedExceptionAction<Void>() {
+      @Override
+      public Void run() throws Exception {
+        updateClient(connectionProps);
+        return null;
+      }
+    });
+
+    // Run few queries using the new client
+    testBuilder()
+        .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
+        .unOrdered()
+        .baselineColumns("session_user")
+        .baselineValues(krbHelper.CLIENT_SHORT_NAME)
+        .go();
+    test("SHOW SCHEMAS");
+    test("USE INFORMATION_SCHEMA");
+    test("SHOW TABLES");
+    test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
+    test("SELECT * FROM cp.`region.json` LIMIT 5");
+  }
+
+  @Test
+  public void successKeytabWithChunking() throws Exception {
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+
+    newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+      .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+        ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+      .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+      .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+        ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+      .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+      .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_ENCRYPTION_SASL_MAX_WRAPPED_SIZE,
+        ConfigValueFactory.fromAnyRef(100))
+      ,false);
+
+    updateTestCluster(1, newConfig, connectionProps);
+
+    // Run few queries using the new client
+    testBuilder()
+      .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
+      .unOrdered()
+      .baselineColumns("session_user")
+      .baselineValues(krbHelper.CLIENT_SHORT_NAME)
+      .go();
+    test("SHOW SCHEMAS");
+    test("USE INFORMATION_SCHEMA");
+    test("SHOW TABLES");
+    test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
+    test("SELECT * FROM cp.`region.json`");
+  }
+
+  @Test
+  public void successKeytabWithChunkingDefaultChunkSize() throws Exception {
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+
+    newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+      .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+        ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+      .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+      .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+        ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+      .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+      .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      ,false);
+
+    updateTestCluster(1, newConfig, connectionProps);
+
+    // Run few queries using the new client
+    testBuilder()
+      .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
+      .unOrdered()
+      .baselineColumns("session_user")
+      .baselineValues(krbHelper.CLIENT_SHORT_NAME)
+      .go();
+    test("SHOW SCHEMAS");
+    test("USE INFORMATION_SCHEMA");
+    test("SHOW TABLES");
+    test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
+    test("SELECT * FROM cp.`region.json` LIMIT 5");
+  }
+
+
+  /**
+   *  This test will not cover the data channel since we are using only 1 Drillbit and the query doesn't involve
+   *  any exchange operator. But Data Channel encryption testing is covered separately in
+   *  {@link org.apache.drill.exec.rpc.data.TestBitBitKerberos}
+   */
+  @Test
+  public void successEncryptionAllChannelChunkMode() throws Exception {
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+
+    newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+      .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+        ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+      .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+      .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+        ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+      .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+      .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_ENCRYPTION_SASL_MAX_WRAPPED_SIZE,
+        ConfigValueFactory.fromAnyRef(10000))
+      .withValue(ExecConstants.BIT_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.BIT_AUTHENTICATION_MECHANISM,
+        ConfigValueFactory.fromAnyRef("kerberos"))
+      .withValue(ExecConstants.USE_LOGIN_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.BIT_ENCRYPTION_SASL_MAX_WRAPPED_SIZE,
+        ConfigValueFactory.fromAnyRef(10000))
+      ,false);
+
+    updateTestCluster(1, newConfig, connectionProps);
+
+    // Run few queries using the new client
+    testBuilder()
+      .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
+      .unOrdered()
+      .baselineColumns("session_user")
+      .baselineValues(krbHelper.CLIENT_SHORT_NAME)
+      .go();
+    test("SHOW SCHEMAS");
+    test("USE INFORMATION_SCHEMA");
+    test("SHOW TABLES");
+    test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
+    test("SELECT * FROM cp.`region.json` LIMIT 5");
+  }
+
+
+
+  /**
+   *  This test will not cover the data channel since we are using only 1 Drillbit and the query doesn't involve
+   *  any exchange operator. But Data Channel encryption testing is covered separately in
+   *  {@link org.apache.drill.exec.rpc.data.TestBitBitKerberos}
+   */
+  @Test
+  public void successEncryptionAllChannel() throws Exception {
+
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+
+    newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+      .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+        ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+      .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+      .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+        ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+      .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+      .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.BIT_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.BIT_AUTHENTICATION_MECHANISM,
+        ConfigValueFactory.fromAnyRef("kerberos"))
+      .withValue(ExecConstants.USE_LOGIN_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      ,false);
+
+    updateTestCluster(1, newConfig, connectionProps);
+
+    // Run few queries using the new client
+    testBuilder()
+      .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
+      .unOrdered()
+      .baselineColumns("session_user")
+      .baselineValues(krbHelper.CLIENT_SHORT_NAME)
+      .go();
+    test("SHOW SCHEMAS");
+    test("USE INFORMATION_SCHEMA");
+    test("SHOW TABLES");
+    test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'");
+    test("SELECT * FROM cp.`region.json` LIMIT 5");
+  }
+
+  @Test
+  public void failurePlainMech() {
+    try {
+      final Properties connectionProps = new Properties();
+      connectionProps.setProperty(DrillProperties.USER, "anonymous");
+      connectionProps.setProperty(DrillProperties.PASSWORD, "anything works!");
+
+      newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+          ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+          ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+        .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+          ConfigValueFactory.fromAnyRef(true)),
+        false);
+
+      updateTestCluster(1, newConfig, connectionProps);
+      fail();
+    } catch (Exception ex) {
+      assert (ex.getCause() instanceof NonTransientRpcException);
+      System.out.println("Caught exception: " + ex.getMessage());
+      logger.info("Caught exception: " + ex.getMessage());
+    }
+  }
+
+  @Test
+  public void encryptionEnabledWithOnlyPlainMech() {
+    try {
+      final Properties connectionProps = new Properties();
+      connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+
+      newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+          ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+          ConfigValueFactory.fromIterable(Lists.newArrayList("plain")))
+        .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+          ConfigValueFactory.fromAnyRef(true)),
+        false);
+      updateTestCluster(1, newConfig, connectionProps);
+
+      fail();
+    } catch (Exception ex) {
+      assert (ex.getCause() instanceof NonTransientRpcException);
+      System.out.println("Caught exception: " + ex.getMessage());
+      logger.info("Caught exception: " + ex.getMessage());
+    }
+  }
+
+  /**
+   * Test to validate that older clients are not allowed to connect to secure cluster
+   * with encryption enabled.
+   */
+  @Test
+  public void failureOldClientEncryptionEnabled() {
+    try {
+      final Properties connectionProps = new Properties();
+      connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+      connectionProps.setProperty(DrillProperties.TEST_SASL_LEVEL, "1");
+
+      newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+          ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+          ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+        .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+          ConfigValueFactory.fromAnyRef(true)),
+        false);
+      updateTestCluster(1, newConfig, connectionProps);
+
+      fail();
+    } catch (Exception ex) {
+      assert (ex.getCause() instanceof RpcException);
+      System.out.println("Caught exception: " + ex.getMessage());
+      logger.info("Caught exception: " + ex.getMessage());
+    }
+  }
+
+  /**
+   * Test to validate that older clients are successfully connecting to secure cluster
+   * with encryption disabled.
+   */
+  @Test
+  public void successOldClientEncryptionDisabled() {
+
+    final Properties connectionProps = new Properties();
+    connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+    connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+    connectionProps.setProperty(DrillProperties.TEST_SASL_LEVEL, "1");
+
+    newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+      .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+        ConfigValueFactory.fromAnyRef(true))
+      .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+        ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+      .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+        ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+      .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+        ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+      .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+        ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos"))),
+      false);
+
+    updateTestCluster(1, newConfig, connectionProps);
+  }
+
+  /**
+   * Test to validate that clients which needs encrypted connection fails to connect
+   * to server with encryption disabled.
+   */
+  @Test
+  public void clientNeedsEncryptionWithNoServerSupport() throws Exception {
+    try {
+      final Properties connectionProps = new Properties();
+      connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+      connectionProps.setProperty(DrillProperties.SASL_ENCRYPT, "true");
+
+      newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+          ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+          ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+        , false);
+
+      updateTestCluster(1, newConfig, connectionProps);
+
+      fail();
+    } catch (Exception ex) {
+      assert (ex.getCause() instanceof NonTransientRpcException);
+    }
+  }
+
+  /**
+   * Test to validate that clients which needs encrypted connection connects
+   * to server with encryption enabled.
+   */
+  @Test
+  public void clientNeedsEncryptionWithServerSupport() throws Exception {
+    try {
+      final Properties connectionProps = new Properties();
+      connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL);
+      connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath());
+      connectionProps.setProperty(DrillProperties.SASL_ENCRYPT, "true");
+
+      newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties())
+        .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED,
+          ConfigValueFactory.fromAnyRef(true))
+        .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL,
+          ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE))
+        .withValue(BootStrapContext.SERVICE_PRINCIPAL,
+          ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL))
+        .withValue(BootStrapContext.SERVICE_KEYTAB_LOCATION,
+          ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString()))
+        .withValue(ExecConstants.AUTHENTICATION_MECHANISMS,
+          ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))
+        .withValue(ExecConstants.USER_ENCRYPTION_SASL_ENABLED,
+              ConfigValueFactory.fromAnyRef(true))
+        , false);
+
+      updateTestCluster(1, newConfig, connectionProps);
+    } catch (Exception ex) {
+      fail();
+      assert (ex.getCause() instanceof NonTransientRpcException);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/AbstractRemoteConnection.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/AbstractRemoteConnection.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/AbstractRemoteConnection.java
index 59ed85b..face1af 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/AbstractRemoteConnection.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/AbstractRemoteConnection.java
@@ -20,27 +20,35 @@ package org.apache.drill.exec.rpc;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.ChannelPipeline;
 import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
 
 import java.net.SocketAddress;
+import java.nio.ByteOrder;
 import java.util.concurrent.ExecutionException;
 
 import org.apache.drill.exec.proto.UserBitShared.DrillPBError;
 
-public abstract class AbstractRemoteConnection implements RemoteConnection {
+public abstract class AbstractRemoteConnection implements RemoteConnection, EncryptionContext {
   private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractRemoteConnection.class);
 
   private final Channel channel;
   private final WriteManager writeManager;
   private final RequestIdMap requestIdMap = new RequestIdMap();
   private final String clientName;
-
   private String name;
 
-  public AbstractRemoteConnection(SocketChannel channel, String name) {
+  // Encryption related parameters
+  private final EncryptionContext encryptionContext;
+  // SaslCodec to hold instance of SaslClient/SaslServer
+  protected SaslCodec saslCodec;
+
+  public AbstractRemoteConnection(SocketChannel channel, String name, EncryptionContext encryptionContext) {
     this.channel = channel;
     this.clientName = name;
     this.writeManager = new WriteManager();
+    this.encryptionContext = new EncryptionContextImpl(encryptionContext);
     channel.pipeline().addLast(new BackPressureHandler());
   }
 
@@ -224,4 +232,98 @@ public abstract class AbstractRemoteConnection implements RemoteConnection {
     }
   }
 
+  /**
+   * Helps to add all the required security handler's after negotiation for encryption is completed.
+   * <p>Handler's before encryption is negotiated are:</p>
+   * <ul>
+   *    <li>  PROTOCOL_DECODER {@link ProtobufLengthDecoder} </li>
+   *    <li>  MESSAGE_DECODER {@link RpcDecoder}  </li>
+   *    <li>  PROTOCOL_ENCODER {@link RpcEncoder} </li>
+   *    <li>  HANDSHAKE_HANDLER {@link org.apache.drill.exec.rpc.BasicClient.ClientHandshakeHandler} OR
+   *                            {@link org.apache.drill.exec.rpc.BasicServer.ServerHandshakeHandler}  </li>
+   *    <li>  optional - IDLE_STATE_HANDLER {@link org.apache.drill.exec.rpc.BasicClient.IdlePingHandler} OR
+   *                   - TIMEOUT_HANDLER {@link org.apache.drill.exec.rpc.BasicServer.LoggingReadTimeoutHandler}  </li>
+   *    <li>  MESSAGE_HANDLER {@link org.apache.drill.exec.rpc.RpcBus.InboundHandler} </li>
+   *    <li>  EXCEPTION_HANDLER {@link RpcExceptionHandler} </li>
+   * </ul>
+   * <p>Handler's after encryption is negotiated are:</p>
+   * <ul>
+   *    <li>  LENGTH_DECODER_HANDLER {@link LengthFieldBasedFrameDecoder}
+   *    <li>  SASL_DECRYPTION_HANDLER {@link SaslDecryptionHandler}
+   *    <li>  PROTOCOL_DECODER {@link ProtobufLengthDecoder}
+   *    <li>  MESSAGE_DECODER {@link RpcDecoder}
+   *    <li>  SASL_ENCRYPTION_HANDLER {@link SaslEncryptionHandler}
+   *    <li>  CHUNK_CREATION_HANDLER {@link ChunkCreationHandler}
+   *    <li>  PROTOCOL_ENCODER {@link RpcEncoder}
+   *    <li>  HANDSHAKE_HANDLER {@link org.apache.drill.exec.rpc.BasicClient.ClientHandshakeHandler} OR
+   *                            {@link org.apache.drill.exec.rpc.BasicServer.ServerHandshakeHandler}
+   *    <li>  optional - IDLE_STATE_HANDLER {@link org.apache.drill.exec.rpc.BasicClient.IdlePingHandler} OR
+   *                   - TIMEOUT_HANDLER {@link org.apache.drill.exec.rpc.BasicServer.LoggingReadTimeoutHandler}
+   *    <li>  MESSAGE_HANDLER {@link org.apache.drill.exec.rpc.RpcBus.InboundHandler}
+   *    <li>  EXCEPTION_HANDLER {@link RpcExceptionHandler}
+   * </ul>
+   * <p>
+   *  If encryption is enabled ChunkCreationHandler is always added to divide the Rpc message into chunks of
+   *  negotiated {@link EncryptionContextImpl#wrapSizeLimit} bytes. This helps to make a generic encryption handler.
+   * </p>
+   */
+  @Override
+  public void addSecurityHandlers() {
+
+    final ChannelPipeline channelPipeline = getChannel().pipeline();
+    channelPipeline.addFirst(RpcConstants.SASL_DECRYPTION_HANDLER,
+        new SaslDecryptionHandler(saslCodec, getMaxWrappedSize(), OutOfMemoryHandler.DEFAULT_INSTANCE));
+
+    channelPipeline.addFirst(RpcConstants.LENGTH_DECODER_HANDLER,
+        new LengthFieldBasedFrameDecoder(ByteOrder.BIG_ENDIAN, Integer.MAX_VALUE,
+            RpcConstants.LENGTH_FIELD_OFFSET, RpcConstants.LENGTH_FIELD_LENGTH,
+            RpcConstants.LENGTH_ADJUSTMENT, RpcConstants.INITIAL_BYTES_TO_STRIP, true));
+
+    channelPipeline.addAfter(RpcConstants.MESSAGE_DECODER, RpcConstants.SASL_ENCRYPTION_HANDLER,
+        new SaslEncryptionHandler(saslCodec, getWrapSizeLimit(),
+            OutOfMemoryHandler.DEFAULT_INSTANCE));
+
+    channelPipeline.addAfter(RpcConstants.SASL_ENCRYPTION_HANDLER, RpcConstants.CHUNK_CREATION_HANDLER,
+        new ChunkCreationHandler(getWrapSizeLimit()));
+  }
+
+  public abstract void incConnectionCounter();
+
+  public abstract void decConnectionCounter();
+
+  @Override
+  public void setEncryption(boolean encrypted) {
+    encryptionContext.setEncryption(encrypted);
+  }
+
+  @Override
+  public boolean isEncryptionEnabled() {
+    return encryptionContext.isEncryptionEnabled();
+  }
+
+  @Override
+  public String getEncryptionCtxtString() {
+    return encryptionContext.toString();
+  }
+
+  @Override
+  public void setMaxWrappedSize(int maxWrappedChunkSize) {
+    encryptionContext.setMaxWrappedSize(maxWrappedChunkSize);
+  }
+
+  @Override
+  public int getMaxWrappedSize() {
+    return encryptionContext.getMaxWrappedSize();
+  }
+
+  @Override
+  public void setWrapSizeLimit(int wrapSizeLimit) {
+    encryptionContext.setWrapSizeLimit(wrapSizeLimit);
+  }
+
+  @Override
+  public int getWrapSizeLimit() {
+    return encryptionContext.getWrapSizeLimit();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicClient.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicClient.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicClient.java
index e418c5a..d51b748 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicClient.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicClient.java
@@ -101,17 +101,17 @@ public abstract class BasicClient<T extends EnumLite, CC extends ClientConnectio
 
             final ChannelPipeline pipe = ch.pipeline();
 
-            pipe.addLast("protocol-decoder", getDecoder(connection.getAllocator()));
-            pipe.addLast("message-decoder", new RpcDecoder("c-" + rpcConfig.getName()));
-            pipe.addLast("protocol-encoder", new RpcEncoder("c-" + rpcConfig.getName()));
-            pipe.addLast("handshake-handler", new ClientHandshakeHandler(connection));
+            pipe.addLast(RpcConstants.PROTOCOL_DECODER, getDecoder(connection.getAllocator()));
+            pipe.addLast(RpcConstants.MESSAGE_DECODER, new RpcDecoder("c-" + rpcConfig.getName()));
+            pipe.addLast(RpcConstants.PROTOCOL_ENCODER, new RpcEncoder("c-" + rpcConfig.getName()));
+            pipe.addLast(RpcConstants.HANDSHAKE_HANDLER, new ClientHandshakeHandler(connection));
 
             if(pingHandler != null){
-              pipe.addLast("idle-state-handler", pingHandler);
+              pipe.addLast(RpcConstants.IDLE_STATE_HANDLER, pingHandler);
             }
 
-            pipe.addLast("message-handler", new InboundHandler(connection));
-            pipe.addLast("exception-handler", new RpcExceptionHandler<CC>(connection));
+            pipe.addLast(RpcConstants.MESSAGE_HANDLER, new InboundHandler(connection));
+            pipe.addLast(RpcConstants.EXCEPTION_HANDLER, new RpcExceptionHandler<CC>(connection));
           }
         }); //
 
@@ -323,5 +323,4 @@ public abstract class BasicClient<T extends EnumLite, CC extends ClientConnectio
       connection.close();
     }
   }
-
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicServer.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
index 7437b65..a7258dd 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/BasicServer.java
@@ -53,8 +53,6 @@ import com.google.protobuf.Parser;
 public abstract class BasicServer<T extends EnumLite, SC extends ServerConnection<SC>> extends RpcBus<T, SC> {
   final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass());
 
-  protected static final String TIMEOUT_HANDLER = "timeout-handler";
-
   private final ServerBootstrap b;
   private volatile boolean connect = false;
   private final EventLoopGroup eventLoopGroup;
@@ -84,18 +82,18 @@ public abstract class BasicServer<T extends EnumLite, SC extends ServerConnectio
             ch.closeFuture().addListener(getCloseHandler(ch, connection));
 
             final ChannelPipeline pipe = ch.pipeline();
-            pipe.addLast("protocol-decoder", getDecoder(connection.getAllocator(), getOutOfMemoryHandler()));
-            pipe.addLast("message-decoder", new RpcDecoder("s-" + rpcConfig.getName()));
-            pipe.addLast("protocol-encoder", new RpcEncoder("s-" + rpcConfig.getName()));
-            pipe.addLast("handshake-handler", getHandshakeHandler(connection));
+            pipe.addLast(RpcConstants.PROTOCOL_DECODER, getDecoder(connection.getAllocator(), getOutOfMemoryHandler()));
+            pipe.addLast(RpcConstants.MESSAGE_DECODER, new RpcDecoder("s-" + rpcConfig.getName()));
+            pipe.addLast(RpcConstants.PROTOCOL_ENCODER, new RpcEncoder("s-" + rpcConfig.getName()));
+            pipe.addLast(RpcConstants.HANDSHAKE_HANDLER, getHandshakeHandler(connection));
 
             if (rpcMapping.hasTimeout()) {
-              pipe.addLast(TIMEOUT_HANDLER,
+              pipe.addLast(RpcConstants.TIMEOUT_HANDLER,
                   new LoggingReadTimeoutHandler(connection, rpcMapping.getTimeout()));
             }
 
-            pipe.addLast("message-handler", new InboundHandler(connection));
-            pipe.addLast("exception-handler", new RpcExceptionHandler<>(connection));
+            pipe.addLast(RpcConstants.MESSAGE_HANDLER, new InboundHandler(connection));
+            pipe.addLast(RpcConstants.EXCEPTION_HANDLER, new RpcExceptionHandler<>(connection));
 
             connect = true;
 //            logger.debug("Server connection initialization completed.");

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ChunkCreationHandler.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ChunkCreationHandler.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ChunkCreationHandler.java
new file mode 100644
index 0000000..b0c1ae0
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ChunkCreationHandler.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc;
+
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.CompositeByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.Math.min;
+
+/**
+ * Handler that converts an input ByteBuf into chunk size ByteBuf's and add it to the
+ * CompositeByteBuf as individual components. If encryption is enabled, this is always
+ * added in the channel pipeline.
+ */
+class ChunkCreationHandler extends MessageToMessageEncoder<ByteBuf> {
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(
+      ChunkCreationHandler.class.getCanonicalName());
+
+  private final int chunkSize;
+
+  ChunkCreationHandler(int chunkSize) {
+    checkArgument(chunkSize > 0);
+    this.chunkSize = chunkSize;
+  }
+
+  @Override
+  public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+    super.handlerAdded(ctx);
+    logger.trace("Added " + RpcConstants.CHUNK_CREATION_HANDLER + " handler!");
+  }
+
+  @Override
+  public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+    super.handlerRemoved(ctx);
+    logger.trace("Removed " + RpcConstants.CHUNK_CREATION_HANDLER + " handler");
+  }
+
+  @Override
+  protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
+
+    if (RpcConstants.EXTRA_DEBUGGING) {
+      logger.debug("ChunkCreationHandler called with msg {} of size {} with chunkSize {}",
+          msg, msg.readableBytes(), chunkSize);
+    }
+
+    if (!ctx.channel().isOpen()) {
+      logger.debug("Channel closed, skipping encode inside {}.", RpcConstants.CHUNK_CREATION_HANDLER);
+      msg.release();
+      return;
+    }
+
+    // Calculate the number of chunks based on configured chunk size and input msg size
+    int numChunks = (int) Math.ceil((double) msg.readableBytes() / chunkSize);
+
+    // Initialize a composite buffer to hold numChunks chunk.
+    final CompositeByteBuf cbb = ctx.alloc().compositeBuffer(numChunks);
+
+    int cbbWriteIndex = 0;
+    int currentChunkLen = min(msg.readableBytes(), chunkSize);
+
+    // Create slices of chunkSize from input msg and add it to the composite buffer.
+    while (numChunks > 0) {
+      final ByteBuf chunkBuf = msg.slice(msg.readerIndex(), currentChunkLen);
+      chunkBuf.retain();
+      cbb.addComponent(chunkBuf);
+      cbbWriteIndex += currentChunkLen;
+      msg.skipBytes(currentChunkLen);
+      --numChunks;
+      currentChunkLen = min(msg.readableBytes(), chunkSize);
+    }
+
+    // Update the writerIndex of composite byte buffer. Netty doesn't do it automatically.
+    cbb.writerIndex(cbbWriteIndex);
+
+    // Add the final composite bytebuf into output buffer.
+    out.add(cbb);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ClientConnection.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ClientConnection.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ClientConnection.java
index 5393173..15e5cf8 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ClientConnection.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ClientConnection.java
@@ -19,7 +19,7 @@ package org.apache.drill.exec.rpc;
 
 import javax.security.sasl.SaslClient;
 
-public interface ClientConnection extends RemoteConnection {
+public interface ClientConnection extends RemoteConnection, EncryptionContext {
 
   // set only once
   void setSaslClient(SaslClient saslClient);
@@ -27,4 +27,7 @@ public interface ClientConnection extends RemoteConnection {
   // get only after setting
   SaslClient getSaslClient();
 
+  // dispose the saslClient object
+  void disposeSaslClient();
+
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContext.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContext.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContext.java
new file mode 100644
index 0000000..dd9acdd
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContext.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.rpc;
+
+public interface EncryptionContext {
+
+  boolean isEncryptionEnabled();
+
+  void setEncryption(boolean encryptionEnabled);
+
+  void setMaxWrappedSize(int maxWrappedChunkSize);
+
+  int getMaxWrappedSize();
+
+  void setWrapSizeLimit(int wrapSizeLimit);
+
+  int getWrapSizeLimit();
+
+  String getEncryptionCtxtString();
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContextImpl.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContextImpl.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContextImpl.java
new file mode 100644
index 0000000..4710823
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/EncryptionContextImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc;
+
+/**
+ * Context to help initializing encryption related configurations for a connection.
+ * <ul>
+ * <li>encryptionEnabled  - identifies if encryption is required or not </li>
+ * <li>maxWrappedSize     - maximum size of the encoded packet that is sent over wire.
+ *                          Recommended Maximum value is {@link RpcConstants#MAX_RECOMMENDED_WRAPPED_SIZE}</li>
+ * <li>wrapSizeLimit      - Maximum size of plain buffer to be send to wrap call which will produce encrypted buffer
+ *                          <= maxWrappedSize. Get's set after SASL negotiation.</li>
+ *</ul>
+ */
+public class EncryptionContextImpl implements EncryptionContext {
+  //private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(EncryptionContextImpl.class);
+
+  private boolean encryptionEnabled;
+
+  private int maxWrappedSize;
+
+  private int wrapSizeLimit;
+
+  EncryptionContextImpl() {
+    this.encryptionEnabled = false;
+    this.maxWrappedSize = 65536;
+    this.wrapSizeLimit = 0;
+  }
+
+  EncryptionContextImpl(EncryptionContext context) {
+    this.encryptionEnabled = context.isEncryptionEnabled();
+    this.maxWrappedSize = context.getMaxWrappedSize();
+    this.wrapSizeLimit = context.getWrapSizeLimit();
+  }
+
+  @Override
+  public boolean isEncryptionEnabled() {
+    return encryptionEnabled;
+  }
+
+  @Override
+  public void setEncryption(boolean encryptionEnabled) {
+    this.encryptionEnabled = encryptionEnabled;
+  }
+
+  @Override
+  public int getMaxWrappedSize() {
+    return maxWrappedSize;
+  }
+
+  @Override
+  public void setMaxWrappedSize(int maxWrappedSize) {
+    this.maxWrappedSize = maxWrappedSize;
+  }
+
+  @Override
+  public String getEncryptionCtxtString() {
+    return toString();
+  }
+
+  @Override
+  public void setWrapSizeLimit(int wrapSizeLimit) {
+    this.wrapSizeLimit = wrapSizeLimit;
+  }
+
+  @Override
+  public int getWrapSizeLimit() {
+    return wrapSizeLimit;
+  }
+
+  private String getEncryptionString() {
+    return encryptionEnabled ? "enabled" : "disabled";
+  }
+
+  @Override
+  public String toString() {
+    return ("Encryption: " + getEncryptionString() + " , MaxWrappedSize: " + maxWrappedSize + " , " +
+        "WrapSizeLimit: " + wrapSizeLimit).intern();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RemoteConnection.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RemoteConnection.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RemoteConnection.java
index ffb7429..d5ddc00 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RemoteConnection.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RemoteConnection.java
@@ -51,6 +51,8 @@ public interface RemoteConnection extends ConnectionThrottle, AutoCloseable {
 
   SocketAddress getRemoteAddress();
 
+  void addSecurityHandlers();
+
   @Override
   void close();
 

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcConstants.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcConstants.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcConstants.java
index 4be365c..be58f37 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcConstants.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcConstants.java
@@ -1,4 +1,4 @@
-/**
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -24,4 +24,29 @@ public class RpcConstants {
 
   public static final boolean SOME_DEBUGGING = false;
   public static final boolean EXTRA_DEBUGGING = false;
+
+  // RPC Handler names
+  public static final String TIMEOUT_HANDLER = "timeout-handler";
+  public static final String PROTOCOL_DECODER = "protocol-decoder";
+  public static final String PROTOCOL_ENCODER = "protocol-encoder";
+  public static final String MESSAGE_DECODER = "message-decoder";
+  public static final String HANDSHAKE_HANDLER = "handshake-handler";
+  public static final String MESSAGE_HANDLER = "message-handler";
+  public static final String EXCEPTION_HANDLER = "exception-handler";
+  public static final String IDLE_STATE_HANDLER = "idle-state-handler";
+  public static final String SASL_DECRYPTION_HANDLER = "sasl-decryption-handler";
+  public static final String SASL_ENCRYPTION_HANDLER = "sasl-encryption-handler";
+  public static final String LENGTH_DECODER_HANDLER = "length-decoder";
+  public static final String CHUNK_CREATION_HANDLER = "chunk-creation-handler";
+
+
+
+  // GSSAPI RFC 2222 allows only 3 octets to specify the length of maximum encoded buffer each side can receive.
+  // Hence the recommended maximum buffer size is kept as 16Mb i.e. 0XFFFFFF bytes.
+  public static final int MAX_RECOMMENDED_WRAPPED_SIZE = 0XFFFFFF;
+
+  public static final int LENGTH_FIELD_OFFSET = 0;
+  public static final int LENGTH_FIELD_LENGTH = 4;
+  public static final int LENGTH_ADJUSTMENT = 0;
+  public static final int INITIAL_BYTES_TO_STRIP = 0;
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcEncoder.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcEncoder.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcEncoder.java
index f9da6f1..19097bd 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcEncoder.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcEncoder.java
@@ -111,7 +111,7 @@ class RpcEncoder extends MessageToMessageEncoder<OutboundRpcMessage>{
         cos.writeRawVarint32(rawBodyLength);
         cos.flush(); // need to flush so that dbody goes after if cos is caching.
 
-        CompositeByteBuf cbb = new CompositeByteBuf(buf.alloc(), true, msg.dBodies.length + 1);
+        final CompositeByteBuf cbb = ctx.alloc().compositeBuffer(msg.dBodies.length + 1);
         cbb.addComponent(buf);
         int bufLength = buf.readableBytes();
         for (ByteBuf b : msg.dBodies) {

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcMetrics.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcMetrics.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcMetrics.java
new file mode 100644
index 0000000..a737095
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/RpcMetrics.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.rpc;
+
+/**
+ * Holder interface for all the metrics used in RPC layer
+ */
+public interface RpcMetrics {
+
+  void addConnectionCount();
+
+  void decConnectionCount();
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslCodec.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslCodec.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslCodec.java
new file mode 100644
index 0000000..582b91c
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslCodec.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.rpc;
+
+import javax.security.sasl.SaslException;
+
+/*
+ * Codec interface which helps to bind wrap/unwrap call in security handlers to corresponding calls on SaslClient
+ * or SaslServer instances.
+ */
+public interface SaslCodec {
+
+  /** Encrypt data. */
+  byte[] wrap(byte[] data, int offset, int len) throws SaslException;
+
+  /** Decrypt data. */
+  byte[] unwrap(byte[] data, int offset, int len) throws SaslException;
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslDecryptionHandler.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslDecryptionHandler.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslDecryptionHandler.java
new file mode 100644
index 0000000..52faf51
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslDecryptionHandler.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.rpc;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageDecoder;
+import org.apache.drill.exec.exception.OutOfMemoryException;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.List;
+
+/**
+ * Handler to Decrypt the input ByteBuf. It expects input to be in format where it has length of the bytes to
+ * decode in network order and actual encrypted bytes. The handler reads the length and then reads the
+ * required bytes to pass it to unwrap function for decryption. The decrypted buffer is copied to a new
+ * ByteBuf and added to out list.
+ * <p>
+ * Example:
+ * <li>Input - [EBLN1, EB1, EBLN2, EB2] --> ByteBuf with repeated combination of encrypted byte length
+ *             in network order (EBLNx) and encrypted bytes (EB)
+ * <li>Output - [DB1] --> Decrypted ByteBuf of first chunk.(EB1)
+ * </p>
+ */
+class SaslDecryptionHandler extends MessageToMessageDecoder<ByteBuf> {
+
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(
+      SaslDecryptionHandler.class.getCanonicalName());
+
+  private final SaslCodec saslCodec;
+
+  private final int maxWrappedSize;
+
+  private final OutOfMemoryHandler outOfMemoryHandler;
+
+  private final byte[] encodedMsg;
+
+  private final ByteBuffer lengthOctets;
+
+  SaslDecryptionHandler(SaslCodec saslCodec, int maxWrappedSize, OutOfMemoryHandler oomHandler) {
+    this.saslCodec = saslCodec;
+    this.outOfMemoryHandler = oomHandler;
+    this.maxWrappedSize = maxWrappedSize;
+
+    // Allocate the byte array of maxWrappedSize to reuse for each encoded packet received on this connection.
+    // Size of this buffer depends upon the configuration encryption.sasl.max_wrapped_size
+    encodedMsg = new byte[maxWrappedSize];
+    lengthOctets = ByteBuffer.allocate(RpcConstants.LENGTH_FIELD_LENGTH);
+    lengthOctets.order(ByteOrder.BIG_ENDIAN);
+  }
+
+  @Override
+  public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+    super.handlerAdded(ctx);
+    logger.trace("Added " + RpcConstants.SASL_DECRYPTION_HANDLER + " handler");
+  }
+
+  @Override
+  public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+    super.handlerRemoved(ctx);
+    logger.trace("Removed " + RpcConstants.SASL_DECRYPTION_HANDLER + " handler");
+  }
+
+  public void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws IOException {
+
+    if (!ctx.channel().isOpen()) {
+      logger.trace("Channel closed before decoding the message of {} bytes", msg.readableBytes());
+      msg.skipBytes(msg.readableBytes());
+      return;
+    }
+
+    try {
+      if(logger.isTraceEnabled()) {
+        logger.trace("Trying to decrypt the encrypted message of size: {} with maxWrappedSize", msg.readableBytes());
+      }
+
+
+      // All the encrypted blocks are prefixed with it's length in network byte order (or BigEndian format). Netty's
+      // default Byte order of ByteBuf is Little Endian, so we cannot just do msg.getInt() as that will read the 4
+      // octets in little endian format.
+      //
+      // We will read the length of one complete encrypted chunk and decode that.
+      msg.getBytes(msg.readerIndex(), lengthOctets.array(), 0, RpcConstants.LENGTH_FIELD_LENGTH);
+      final int wrappedMsgLength = lengthOctets.getInt(0);
+      msg.skipBytes(RpcConstants.LENGTH_FIELD_LENGTH);
+
+      // Since lengthBasedFrameDecoder will ensure we have enough bytes it's good to have this check here.
+      assert(msg.readableBytes() == wrappedMsgLength);
+
+      // Uncomment the below code if msg can contain both of Direct and Heap ByteBuf. Currently Drill only supports
+      // DirectByteBuf so the below condition will always be false. If the msg are always HeapByteBuf then in
+      // addition also remove the allocation of encodedMsg from constructor.
+      /*if (msg.hasArray()) {
+        wrappedMsg = msg.array();
+      } else {
+      if (RpcConstants.EXTRA_DEBUGGING) {
+        logger.debug("The input bytebuf is not backed by a byte array so allocating a new one");
+      }*/
+
+      // Check if the wrappedMsgLength doesn't exceed agreed upon maxWrappedSize. As per SASL RFC 2222/4422 we
+      // should close the connection since it represents a security attack.
+      if (wrappedMsgLength > maxWrappedSize) {
+        throw new RpcException(String.format("Received encoded buffer size: %d is larger than negotiated " +
+            "maxWrappedSize: %d. Closing the connection as this is unexpected.", wrappedMsgLength, maxWrappedSize));
+      }
+
+      final byte[] wrappedMsg = encodedMsg;
+      // Copy the wrappedMsgLength of bytes into the byte array
+      msg.getBytes(msg.readerIndex(), wrappedMsg, 0, wrappedMsgLength);
+      //}
+
+      // SASL library always copies the origMsg internally to a new byte array
+      // and return another new byte array after decrypting the message. The memory for this
+      // will be Garbage collected by JVM since SASL Library releases it's reference after
+      // returning the byte array.
+      final byte[] decodedMsg = saslCodec.unwrap(wrappedMsg, 0, wrappedMsgLength);
+
+      if(logger.isTraceEnabled()) {
+        logger.trace("Successfully decrypted incoming message. Length after decryption: {}", decodedMsg.length);
+      }
+
+      // Update the msg reader index since we have decrypted this chunk
+      msg.skipBytes(wrappedMsgLength);
+
+      // Allocate a new Bytebuf to copy the decrypted chunk.
+      final ByteBuf decodedMsgBuf = ctx.alloc().buffer(decodedMsg.length);
+      decodedMsgBuf.writeBytes(decodedMsg);
+
+      // Add the decrypted chunk to output buffer for next handler to take care of it.
+      out.add(decodedMsgBuf);
+
+    } catch (OutOfMemoryException e) {
+      logger.warn("Failure allocating buffer on incoming stream due to memory limits.");
+      msg.resetReaderIndex();
+      outOfMemoryHandler.handle();
+    } catch (IOException e) {
+      logger.error("Something went wrong while unwrapping the message: {} with MaxEncodeSize: {} and " +
+          "error: {}", msg, maxWrappedSize, e.getMessage());
+      throw e;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslEncryptionHandler.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslEncryptionHandler.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslEncryptionHandler.java
new file mode 100644
index 0000000..10755c3
--- /dev/null
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/SaslEncryptionHandler.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.rpc;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.CompositeByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageEncoder;
+import org.apache.drill.exec.exception.OutOfMemoryException;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.List;
+
+
+/**
+ * Handler to wrap the input Composite ByteBuf components separately and append the encrypted length for each
+ * component in the output ByteBuf. If there are multiple components in the input ByteBuf then each component will be
+ * encrypted individually and added to output ByteBuf with it's length prepended.
+ * <p>
+ * Example:
+ * <li>Input ByteBuf  --> [B1,B2] - 2 component ByteBuf of 16K byte each.
+ * <li>Output ByteBuf --> [[EBLN1, EB1], [EBLN2, EB2]] - List of ByteBuf's with each ByteBuf containing
+ *                    Encrypted Byte Length (EBLNx) in network order as per SASL RFC and Encrypted Bytes (EBx).
+ * </p>
+ */
+class SaslEncryptionHandler extends MessageToMessageEncoder<ByteBuf> {
+
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(
+      SaslEncryptionHandler.class.getCanonicalName());
+
+  private final SaslCodec saslCodec;
+
+  private final int wrapSizeLimit;
+
+  private byte[] origMsgBuffer;
+
+  private final ByteBuffer lengthOctets;
+
+  private final OutOfMemoryHandler outOfMemoryHandler;
+
+  /**
+   * We don't provide preference to allocator to use heap buffer instead of direct buffer.
+   * Drill uses it's own buffer allocator which doesn't support heap buffer allocation. We use
+   * Drill buffer allocator in the channel.
+   */
+  SaslEncryptionHandler(SaslCodec saslCodec, final int wrapSizeLimit, final OutOfMemoryHandler oomHandler) {
+    this.saslCodec = saslCodec;
+    this.wrapSizeLimit = wrapSizeLimit;
+    this.outOfMemoryHandler = oomHandler;
+
+    // The maximum size of the component will be wrapSizeLimit. Since this is maximum size, we can allocate once
+    // and reuse it for each component encode.
+    origMsgBuffer = new byte[this.wrapSizeLimit];
+    lengthOctets = ByteBuffer.allocate(RpcConstants.LENGTH_FIELD_LENGTH);
+    lengthOctets.order(ByteOrder.BIG_ENDIAN);
+  }
+
+  @Override
+  public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+    super.handlerAdded(ctx);
+    logger.trace("Added " + RpcConstants.SASL_ENCRYPTION_HANDLER + " handler!");
+  }
+
+  @Override
+  public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+    super.handlerRemoved(ctx);
+    logger.trace("Removed " + RpcConstants.SASL_ENCRYPTION_HANDLER + " handler");
+  }
+
+  public void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws IOException {
+
+    if (!ctx.channel().isOpen()) {
+      logger.debug("In " + RpcConstants.SASL_ENCRYPTION_HANDLER + " and channel is not open. " +
+          "So releasing msg memory before encryption.");
+      msg.release();
+      return;
+    }
+
+    try {
+      // If encryption is enabled then this handler will always get ByteBuf of type Composite ByteBuf
+      assert(msg instanceof CompositeByteBuf);
+
+      final CompositeByteBuf cbb = (CompositeByteBuf) msg;
+      final int numComponents = cbb.numComponents();
+
+      // Get all the components inside the Composite ByteBuf for encryption
+      for(int currentIndex = 0; currentIndex < numComponents; ++currentIndex) {
+        final ByteBuf component = cbb.component(currentIndex);
+
+        // Each component ByteBuf size should not be greater than wrapSizeLimit since ChunkCreationHandler
+        // will break the RPC message into chunks of wrapSizeLimit.
+        if (component.readableBytes() > wrapSizeLimit) {
+          throw new RpcException(String.format("Component Chunk size: %d is greater than the wrapSizeLimit: %d",
+              component.readableBytes(), wrapSizeLimit));
+        }
+
+        // Uncomment the below code if msg can contain both of Direct and Heap ByteBuf. Currently Drill only supports
+        // DirectByteBuf so the below condition will always be false. If the msg are always HeapByteBuf then in
+        // addition also remove the allocation of origMsgBuffer from constructor.
+        /*if (component.hasArray()) {
+          origMsg = component.array();
+        } else {
+
+        if (RpcConstants.EXTRA_DEBUGGING) {
+          logger.trace("The input bytebuf is not backed by a byte array so allocating a new one");
+        }*/
+        final byte[] origMsg = origMsgBuffer;
+        component.getBytes(component.readerIndex(), origMsg, 0, component.readableBytes());
+        //}
+
+        if(logger.isTraceEnabled()) {
+          logger.trace("Trying to encrypt chunk of size:{} with wrapSizeLimit:{} and chunkMode: {}",
+              component.readableBytes(), wrapSizeLimit);
+        }
+
+        // Length to encrypt will be component length not origMsg length since that can be greater.
+        final byte[] wrappedMsg = saslCodec.wrap(origMsg, 0, component.readableBytes());
+
+        if(logger.isTraceEnabled()) {
+          logger.trace("Successfully encrypted message, original size: {} Final Size: {}",
+              component.readableBytes(), wrappedMsg.length);
+        }
+
+        // Allocate the buffer (directByteBuff) for copying the encrypted byte array and 4 octets for length of the
+        // encrypted message. This is preferred since later on if the passed buffer is not in direct memory then it
+        // will be copied by the channel into a temporary direct memory which will be cached to the thread. The size
+        // of that temporary direct memory will be size of largest message send.
+        final ByteBuf encryptedBuf = ctx.alloc().buffer(wrappedMsg.length + RpcConstants.LENGTH_FIELD_LENGTH);
+
+        // Based on SASL RFC 2222/4422 we should have starting 4 octet as the length of the encrypted buffer in network
+        // byte order. SASL framework provided by JDK doesn't do that by default and leaves it upto application. Whereas
+        // Cyrus SASL implementation of sasl_encode does take care of this.
+        lengthOctets.putInt(wrappedMsg.length);
+        encryptedBuf.writeBytes(lengthOctets.array());
+
+        // reset the position for re-use in next round
+        lengthOctets.rewind();
+
+        // Write the encrypted bytes inside the buffer
+        encryptedBuf.writeBytes(wrappedMsg);
+
+        // Update the msg and component reader index
+        msg.skipBytes(component.readableBytes());
+        component.skipBytes(component.readableBytes());
+
+        // Add the encrypted buffer into the output to send it on wire.
+        out.add(encryptedBuf);
+      }
+    } catch (OutOfMemoryException e) {
+      logger.warn("Failure allocating buffer on incoming stream due to memory limits.");
+      msg.resetReaderIndex();
+      outOfMemoryHandler.handle();
+    } catch (IOException e) {
+      logger.error("Something went wrong while wrapping the message: {} with MaxRawWrapSize: {}, ChunkMode: {} " +
+          "and error: {}", msg, wrapSizeLimit, e.getMessage());
+      throw e;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ServerConnection.java
----------------------------------------------------------------------
diff --git a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ServerConnection.java b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ServerConnection.java
index 3cdfdb2..6f878ef 100644
--- a/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ServerConnection.java
+++ b/exec/rpc/src/main/java/org/apache/drill/exec/rpc/ServerConnection.java
@@ -20,7 +20,7 @@ package org.apache.drill.exec.rpc;
 import javax.security.sasl.SaslServer;
 import java.io.IOException;
 
-public interface ServerConnection<S extends ServerConnection<S>> extends RemoteConnection {
+public interface ServerConnection<S extends ServerConnection<S>> extends RemoteConnection, EncryptionContext {
 
   // init only once
   void initSaslServer(String mechanismName) throws IOException;
@@ -34,4 +34,6 @@ public interface ServerConnection<S extends ServerConnection<S>> extends RemoteC
 
   void changeHandlerTo(RequestHandler<S> handler);
 
+  void disposeSaslServer();
+
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 9a7ed29..071f086 100644
--- a/pom.xml
+++ b/pom.xml
@@ -229,6 +229,8 @@
             <exclude>**/cmake_install.cmake</exclude>
             <exclude>**/*.tbl</exclude>
             <exclude>**/*.httpd</exclude>
+            <exclude>**/*.autotools</exclude>
+            <exclude>**/*.cproject</exclude>
             <!-- TODO DRILL-4336: try to avoid the need to add this -->
             <exclude>dependency-reduced-pom.xml</exclude>
           </excludes>

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/protocol/readme.txt
----------------------------------------------------------------------
diff --git a/protocol/readme.txt b/protocol/readme.txt
index 6f502c4..9fdaf19 100644
--- a/protocol/readme.txt
+++ b/protocol/readme.txt
@@ -4,10 +4,24 @@ The java sources are generated into src/main/java and checked in.
 
 To regenerate the sources after making changes to .proto files
 ---------------------------------------------------------------
-1. Ensure that the protobuf 'protoc' tool (version 2.5 or newer) is
+1. Ensure that the protobuf 'protoc' tool (version 2.5 or newer (but 2.x series)) is
 in your PATH (you may need to download and build it first). You can 
 download it from http://code.google.com/p/protobuf/downloads/list.
 
+    Note: If generating sources on MAC follow below instructions:
+
+              a) Download and install "brew"
+                 Command: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+
+              b) Download and install "protoc"
+                 Command: brew install protobuf250  --- installs protobuf for version 2.5.0
+                          brew install protobuf     --- installs latest protobuf version
+
+              c) Check the version of "protoc"
+                 Command: protoc --version
+
+              d) Follow steps 2 and 3 below
+
 2. In protocol dir, run "mvn process-sources -P proto-compile" or "mvn clean install -P proto-compile".
 
 3. Check in the new/updated files.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
----------------------------------------------------------------------
diff --git a/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java b/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
index 4bb2de7..b6c2bf4 100644
--- a/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
+++ b/protocol/src/main/java/org/apache/drill/exec/proto/SchemaUserProtos.java
@@ -997,6 +997,10 @@ public final class SchemaUserProtos
                     output.writeString(7, authenticationMechanisms, true);
                 for(org.apache.drill.exec.proto.UserProtos.RpcType supportedMethods : message.getSupportedMethodsList())
                     output.writeEnum(8, supportedMethods.getNumber(), true);
+                if(message.hasEncrypted())
+                    output.writeBool(9, message.getEncrypted(), false);
+                if(message.hasMaxWrappedSize())
+                    output.writeInt32(10, message.getMaxWrappedSize(), false);
             }
             public boolean isInitialized(org.apache.drill.exec.proto.UserProtos.BitToUserHandshake message)
             {
@@ -1058,6 +1062,12 @@ public final class SchemaUserProtos
                         case 8:
                             builder.addSupportedMethods(org.apache.drill.exec.proto.UserProtos.RpcType.valueOf(input.readEnum()));
                             break;
+                        case 9:
+                            builder.setEncrypted(input.readBool());
+                            break;
+                        case 10:
+                            builder.setMaxWrappedSize(input.readInt32());
+                            break;
                         default:
                             input.handleUnknownField(number, this);
                     }
@@ -1105,6 +1115,8 @@ public final class SchemaUserProtos
                 case 6: return "serverInfos";
                 case 7: return "authenticationMechanisms";
                 case 8: return "supportedMethods";
+                case 9: return "encrypted";
+                case 10: return "maxWrappedSize";
                 default: return null;
             }
         }
@@ -1123,6 +1135,8 @@ public final class SchemaUserProtos
             fieldMap.put("serverInfos", 6);
             fieldMap.put("authenticationMechanisms", 7);
             fieldMap.put("supportedMethods", 8);
+            fieldMap.put("encrypted", 9);
+            fieldMap.put("maxWrappedSize", 10);
         }
     }
 


[4/6] drill git commit: DRILL-4335: Apache Drill should support network encryption.

Posted by am...@apache.org.
DRILL-4335: Apache Drill should support network encryption.

    NOTE: This pull request provides support for on-wire encryption using SASL framework. The communication channel that are covered are:
    1) Between Drill JDBC client and Drillbit.
    2) Between Drillbit to Drillbit i.e. control/data channels.
    3) It has UI change to view encryption is enabled on which network channel and number of encrypted/unencrypted connections for
       user/control/data connections.

close apache/drill#773


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/ce8bbc01
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/ce8bbc01
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/ce8bbc01

Branch: refs/heads/master
Commit: ce8bbc01cfde7d714185919be2ca2923d19ea890
Parents: 416ec70
Author: Sorabh Hamirwasia <sh...@maprtech.com>
Authored: Wed Feb 1 18:44:21 2017 -0800
Committer: Aman Sinha <as...@maprtech.com>
Committed: Sat May 20 16:16:21 2017 -0700

----------------------------------------------------------------------
 .../drill/common/config/DrillProperties.java    |  16 +
 .../org/apache/drill/exec/ExecConstants.java    |   5 +
 .../exec/rpc/AbstractClientConnection.java      |  42 +-
 .../exec/rpc/AbstractConnectionConfig.java      |  11 +
 .../drill/exec/rpc/AbstractRpcMetrics.java      |  52 ++
 .../exec/rpc/AbstractServerConnection.java      |  55 +-
 .../drill/exec/rpc/BitConnectionConfig.java     |  32 +-
 .../apache/drill/exec/rpc/ConnectionConfig.java |   3 +
 .../drill/exec/rpc/control/ControlClient.java   |  15 +-
 .../exec/rpc/control/ControlConnection.java     |  45 +-
 .../exec/rpc/control/ControlRpcMetrics.java     |  84 +++
 .../drill/exec/rpc/control/ControlServer.java   |   8 +-
 .../drill/exec/rpc/control/ControllerImpl.java  |   3 +
 .../apache/drill/exec/rpc/data/DataClient.java  |  21 +-
 .../exec/rpc/data/DataClientConnection.java     |  16 +-
 .../exec/rpc/data/DataConnectionCreator.java    |   5 +-
 .../drill/exec/rpc/data/DataRpcMetrics.java     |  85 +++
 .../apache/drill/exec/rpc/data/DataServer.java  |   8 +-
 .../exec/rpc/data/DataServerConnection.java     |   9 +
 .../security/AuthenticationOutcomeListener.java | 104 +++-
 .../rpc/security/AuthenticatorProviderImpl.java |   1 -
 .../security/ClientAuthenticatorProvider.java   |   2 +-
 .../drill/exec/rpc/security/SaslProperties.java |  70 +++
 .../security/ServerAuthenticationHandler.java   |  96 +++-
 .../rpc/security/kerberos/KerberosFactory.java  |  24 +-
 .../apache/drill/exec/rpc/user/UserClient.java  |  80 ++-
 .../exec/rpc/user/UserConnectionConfig.java     |  39 +-
 .../drill/exec/rpc/user/UserRpcMetrics.java     |  84 +++
 .../apache/drill/exec/rpc/user/UserServer.java  |  38 +-
 .../user/security/UserAuthenticatorFactory.java |   6 +
 .../drill/exec/server/rest/DrillRoot.java       |  21 +-
 .../drill/exec/service/ServiceEngine.java       |  50 +-
 .../src/main/resources/drill-module.conf        |   8 +
 .../java-exec/src/main/resources/rest/index.ftl |  21 +
 .../drill/exec/rpc/data/TestBitBitKerberos.java | 326 ++++++-----
 .../apache/drill/exec/rpc/data/TestBitRpc.java  |  18 +-
 .../drill/exec/rpc/security/KerberosHelper.java | 150 +++++
 .../rpc/user/security/TestUserBitKerberos.java  | 163 ++----
 .../security/TestUserBitKerberosEncryption.java | 539 ++++++++++++++++++
 .../exec/rpc/AbstractRemoteConnection.java      | 108 +++-
 .../org/apache/drill/exec/rpc/BasicClient.java  |  15 +-
 .../org/apache/drill/exec/rpc/BasicServer.java  |  16 +-
 .../drill/exec/rpc/ChunkCreationHandler.java    |  99 ++++
 .../apache/drill/exec/rpc/ClientConnection.java |   5 +-
 .../drill/exec/rpc/EncryptionContext.java       |  37 ++
 .../drill/exec/rpc/EncryptionContextImpl.java   |  95 ++++
 .../apache/drill/exec/rpc/RemoteConnection.java |   2 +
 .../org/apache/drill/exec/rpc/RpcConstants.java |  27 +-
 .../org/apache/drill/exec/rpc/RpcEncoder.java   |   2 +-
 .../org/apache/drill/exec/rpc/RpcMetrics.java   |  29 +
 .../org/apache/drill/exec/rpc/SaslCodec.java    |  34 ++
 .../drill/exec/rpc/SaslDecryptionHandler.java   | 160 ++++++
 .../drill/exec/rpc/SaslEncryptionHandler.java   | 177 ++++++
 .../apache/drill/exec/rpc/ServerConnection.java |   4 +-
 pom.xml                                         |   2 +
 protocol/readme.txt                             |  16 +-
 .../drill/exec/proto/SchemaUserProtos.java      |  14 +
 .../org/apache/drill/exec/proto/UserProtos.java | 547 ++++++++++++-------
 .../exec/proto/beans/BitToUserHandshake.java    |  44 ++
 .../drill/exec/proto/beans/SaslSupport.java     |   4 +-
 protocol/src/main/protobuf/User.proto           |   3 +
 61 files changed, 3122 insertions(+), 673 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/common/src/main/java/org/apache/drill/common/config/DrillProperties.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/drill/common/config/DrillProperties.java b/common/src/main/java/org/apache/drill/common/config/DrillProperties.java
index c7e6e29..75064e0 100644
--- a/common/src/main/java/org/apache/drill/common/config/DrillProperties.java
+++ b/common/src/main/java/org/apache/drill/common/config/DrillProperties.java
@@ -17,6 +17,7 @@
  */
 package org.apache.drill.common.config;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableSet;
 import org.apache.drill.exec.proto.UserProtos.Property;
 import org.apache.drill.exec.proto.UserProtos.UserProperties;
@@ -59,6 +60,12 @@ public final class DrillProperties extends Properties {
 
   public static final String KEYTAB = "keytab";
 
+  public static final String SASL_ENCRYPT = "sasl_encrypt";
+
+  // Should only be used for testing backward compatibility
+  @VisibleForTesting
+  public static final String TEST_SASL_LEVEL = "test_sasl_level";
+
   // for subject that has pre-authenticated to KDC (AS) i.e. required credentials are populated in
   // Subject's credentials set
   public static final String KERBEROS_FROM_SUBJECT = "from_subject";
@@ -110,6 +117,15 @@ public final class DrillProperties extends Properties {
     }
   }
 
+  public void merge(final Map<String, String> overrides) {
+    if (overrides == null) {
+      return;
+    }
+    for (final String key : overrides.keySet()) {
+      setProperty(key.toLowerCase(), overrides.get(key));
+    }
+  }
+
   /**
    * Returns a map of keys and values in this property list where the key and its corresponding value are strings,
    * including distinct keys in the default property list if a key of the same name has not already been found from

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
index e291524..007e39a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
@@ -116,6 +116,11 @@ public interface ExecConstants {
   String BIT_AUTHENTICATION_ENABLED = "drill.exec.security.bit.auth.enabled";
   String BIT_AUTHENTICATION_MECHANISM = "drill.exec.security.bit.auth.mechanism";
   String USE_LOGIN_PRINCIPAL = "drill.exec.security.bit.auth.use_login_principal";
+  String USER_ENCRYPTION_SASL_ENABLED = "drill.exec.security.user.encryption.sasl.enabled";
+  String USER_ENCRYPTION_SASL_MAX_WRAPPED_SIZE = "drill.exec.security.user.encryption.sasl.max_wrapped_size";
+  String BIT_ENCRYPTION_SASL_ENABLED = "drill.exec.security.bit.encryption.sasl.enabled";
+  String BIT_ENCRYPTION_SASL_MAX_WRAPPED_SIZE = "drill.exec.security.bit.encryption.sasl.max_wrapped_size";
+
   /** Size of JDBC batch queue (in batches) above which throttling begins. */
   String JDBC_BATCH_QUEUE_THROTTLING_THRESHOLD =
       "drill.jdbc.batch_queue_throttling_threshold";

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractClientConnection.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractClientConnection.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractClientConnection.java
index 055ea59..ab13c2a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractClientConnection.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractClientConnection.java
@@ -30,8 +30,13 @@ public abstract class AbstractClientConnection extends AbstractRemoteConnection
 
   private SaslClient saslClient;
 
+  public AbstractClientConnection(SocketChannel channel, String name,
+                                  EncryptionContext encryptContext) {
+    super(channel, name, encryptContext);
+  }
+
   public AbstractClientConnection(SocketChannel channel, String name) {
-    super(channel, name);
+    this(channel, name, new EncryptionContextImpl());
   }
 
   protected abstract Logger getLogger();
@@ -40,6 +45,25 @@ public abstract class AbstractClientConnection extends AbstractRemoteConnection
   public void setSaslClient(final SaslClient saslClient) {
     checkState(this.saslClient == null);
     this.saslClient = saslClient;
+
+    // If encryption is enabled set the backend wrapper instance corresponding to this SaslClient in the connection
+    // object. This is later used to do wrap/unwrap in handlers.
+    if (isEncryptionEnabled()) {
+      saslCodec = new SaslCodec() {
+
+        @Override
+        public byte[] wrap(byte[] data, int offset, int len) throws SaslException {
+          checkState(saslClient != null);
+          return saslClient.wrap(data, offset, len);
+        }
+
+        @Override
+        public byte[] unwrap(byte[] data, int offset, int len) throws SaslException {
+          checkState(saslClient != null);
+          return saslClient.unwrap(data, offset, len);
+        }
+      };
+    }
   }
 
   @Override
@@ -49,7 +73,7 @@ public abstract class AbstractClientConnection extends AbstractRemoteConnection
   }
 
   @Override
-  public void close() {
+  public void disposeSaslClient() {
     try {
       if (saslClient != null) {
         saslClient.dispose();
@@ -58,6 +82,18 @@ public abstract class AbstractClientConnection extends AbstractRemoteConnection
     } catch (final SaslException e) {
       getLogger().warn("Unclean disposal", e);
     }
-    super.close();
+  }
+
+  @Override
+  public void channelClosed(RpcException ex) {
+    // This will be triggered from Netty when a channel is closed. We should cleanup here
+    // as this will handle case for both client closing the connection or server closing the
+    // connection.
+    disposeSaslClient();
+
+    // Decrease the connection counter here since the close handler will be triggered
+    // for all the types of connection
+    decConnectionCounter();
+    super.channelClosed(ex);
   }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractConnectionConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractConnectionConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractConnectionConfig.java
index fb815ab..76c17e5 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractConnectionConfig.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractConnectionConfig.java
@@ -26,10 +26,12 @@ public abstract class AbstractConnectionConfig implements ConnectionConfig {
 
   private final BufferAllocator allocator;
   private final BootStrapContext context;
+  protected EncryptionContext encryptionContext;
 
   protected AbstractConnectionConfig(BufferAllocator allocator, BootStrapContext context) {
     this.allocator = allocator;
     this.context = context;
+    this.encryptionContext = new EncryptionContextImpl();
   }
 
   @Override
@@ -46,4 +48,13 @@ public abstract class AbstractConnectionConfig implements ConnectionConfig {
   public AuthenticatorProvider getAuthProvider() {
     return context.getAuthProvider();
   }
+
+  @Override
+  public boolean isEncryptionEnabled() {
+    return encryptionContext.isEncryptionEnabled();
+  }
+
+  public EncryptionContext getEncryptionCtxt() {
+    return encryptionContext;
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractRpcMetrics.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractRpcMetrics.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractRpcMetrics.java
new file mode 100644
index 0000000..a1fd308
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractRpcMetrics.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc;
+
+import com.codahale.metrics.Gauge;
+import io.netty.buffer.PooledByteBufAllocatorL;
+import org.apache.drill.exec.memory.BufferAllocator;
+import org.apache.drill.exec.metrics.DrillMetrics;
+
+public abstract class AbstractRpcMetrics implements RpcMetrics {
+  //private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractRpcMetrics.class);
+
+  protected boolean useEncryptedCounter;
+
+  public static final String CONNECTION_COUNTER_PREFIX = "drill.connections.rpc.";
+
+  public static final String ALLOCATOR_METRICS_PREFIX = PooledByteBufAllocatorL.METRIC_PREFIX + "rpc.";
+
+  protected void registerAllocatorMetrics(final BufferAllocator allocator, final String metricPrefix) {
+    DrillMetrics.register(metricPrefix + "used", new Gauge<Long>() {
+      @Override
+      public Long getValue() {
+        return allocator.getAllocatedMemory();
+      }
+    });
+
+    DrillMetrics.register(metricPrefix + "peak", new Gauge<Long>() {
+      @Override
+      public Long getValue() {
+        return allocator.getPeakMemoryAllocation();
+      }
+    });
+  }
+
+  public abstract void initialize(boolean useEncryptedCounter, BufferAllocator allocator);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractServerConnection.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractServerConnection.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractServerConnection.java
index db87bfc..f10f6d0 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractServerConnection.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/AbstractServerConnection.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec.rpc;
 
 import io.netty.channel.socket.SocketChannel;
 import org.apache.drill.exec.memory.BufferAllocator;
+import org.apache.drill.exec.rpc.security.SaslProperties;
 import org.apache.hadoop.security.HadoopKerberosName;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.slf4j.Logger;
@@ -42,7 +43,7 @@ public abstract class AbstractServerConnection<S extends ServerConnection<S>>
 
   public AbstractServerConnection(SocketChannel channel, String name, ConnectionConfig config,
                                   RequestHandler<S> handler) {
-    super(channel, name);
+    super(channel, name, config.getEncryptionCtxt());
     this.config = config;
     this.currentHandler = handler;
   }
@@ -65,8 +66,8 @@ public abstract class AbstractServerConnection<S extends ServerConnection<S>>
     try {
       this.saslServer = config.getAuthProvider()
           .getAuthenticatorFactory(mechanismName)
-          .createSaslServer(UserGroupInformation.getLoginUser(), null
-              /** properties; default QOP is auth */);
+          .createSaslServer(UserGroupInformation.getLoginUser(),
+              SaslProperties.getSaslProperties(isEncryptionEnabled(), getMaxWrappedSize()));
     } catch (final IOException e) {
       getLogger().debug("Login failed.", e);
       final Throwable cause = e.getCause();
@@ -76,7 +77,27 @@ public abstract class AbstractServerConnection<S extends ServerConnection<S>>
       throw new SaslException("Unexpected failure trying to login.", cause);
     }
     if (saslServer == null) {
-      throw new SaslException("Server could not initiate authentication. Insufficient parameters?");
+      throw new SaslException(String.format("Server cannot initiate authentication using %s mechanism. Insufficient" +
+          " parameters or selected mechanism doesn't support configured security layers ?", mechanismName));
+    }
+
+    // If encryption is enabled set the backend wrapper instance corresponding to this SaslServer in the connection
+    // object. This is later used to do wrap/unwrap in handlers.
+    if (isEncryptionEnabled()) {
+      saslCodec = new SaslCodec() {
+
+        @Override
+        public byte[] wrap(byte[] data, int offset, int len) throws SaslException {
+          checkState(saslServer != null);
+          return saslServer.wrap(data, offset, len);
+        }
+
+        @Override
+        public byte[] unwrap(byte[] data, int offset, int len) throws SaslException {
+          checkState(saslServer != null);
+          return saslServer.unwrap(data, offset, len);
+        }
+      };
     }
   }
 
@@ -110,7 +131,17 @@ public abstract class AbstractServerConnection<S extends ServerConnection<S>>
   }
 
   @Override
-  public void close() {
+  public void setEncryption(boolean encrypted) {
+    throw new UnsupportedOperationException("Changing encryption setting on server connection is not permitted.");
+  }
+
+  @Override
+  public void setMaxWrappedSize(int maxWrappedSize) {
+    throw new UnsupportedOperationException("Changing maxWrappedSize setting on server connection is not permitted.");
+  }
+
+  @Override
+  public void disposeSaslServer() {
     try {
       if (saslServer != null) {
         saslServer.dispose();
@@ -119,6 +150,18 @@ public abstract class AbstractServerConnection<S extends ServerConnection<S>>
     } catch (final SaslException e) {
       getLogger().warn("Unclean disposal.", e);
     }
-    super.close();
+  }
+
+  @Override
+  public void channelClosed(RpcException ex) {
+    // This will be triggered from Netty when a channel is closed. We should cleanup here
+    // as this will handle case for both client closing the connection or server closing the
+    // connection.
+    disposeSaslServer();
+
+    // Decrease the connection counter here since the close handler will be triggered
+    // for all the types of connection
+    decConnectionCounter();
+    super.channelClosed(ex);
   }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BitConnectionConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BitConnectionConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BitConnectionConfig.java
index 71e5a86..7d9ebec 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BitConnectionConfig.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/BitConnectionConfig.java
@@ -26,6 +26,7 @@ import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint;
 import org.apache.drill.exec.rpc.security.AuthStringUtil;
 import org.apache.drill.exec.rpc.security.AuthenticatorFactory;
+import org.apache.drill.exec.rpc.security.AuthenticatorProvider;
 import org.apache.drill.exec.server.BootStrapContext;
 import org.apache.hadoop.security.HadoopKerberosName;
 import org.apache.hadoop.security.UserGroupInformation;
@@ -46,16 +47,38 @@ public abstract class BitConnectionConfig extends AbstractConnectionConfig {
     super(allocator, context);
 
     final DrillConfig config = context.getConfig();
+    final AuthenticatorProvider authProvider = getAuthProvider();
+
     if (config.getBoolean(ExecConstants.BIT_AUTHENTICATION_ENABLED)) {
       this.authMechanismToUse = config.getString(ExecConstants.BIT_AUTHENTICATION_MECHANISM);
       try {
-        getAuthProvider().getAuthenticatorFactory(authMechanismToUse);
+        authProvider.getAuthenticatorFactory(authMechanismToUse);
       } catch (final SaslException e) {
         throw new DrillbitStartupException(String.format(
             "'%s' mechanism not found for bit-to-bit authentication. Please check authentication configuration.",
             authMechanismToUse));
       }
-      logger.info("Configured bit-to-bit connections to require authentication using: {}", authMechanismToUse);
+
+      // Update encryption related configurations
+      encryptionContext.setEncryption(config.getBoolean(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED));
+      final int maxWrappedSize = config.getInt(ExecConstants.BIT_ENCRYPTION_SASL_MAX_WRAPPED_SIZE);
+
+      if (maxWrappedSize <= 0) {
+        throw new DrillbitStartupException(String.format("Invalid value configured for " +
+            "bit.encryption.sasl.max_wrapped_size. Must be a positive integer in bytes with a recommended max value " +
+            "of %s", RpcConstants.MAX_RECOMMENDED_WRAPPED_SIZE));
+      } else if (maxWrappedSize > RpcConstants.MAX_RECOMMENDED_WRAPPED_SIZE) {
+        logger.warn("The configured value of bit.encryption.sasl.max_wrapped_size is too big. This may cause higher" +
+            " memory pressure. [Details: Recommended max value is %s]", RpcConstants.MAX_RECOMMENDED_WRAPPED_SIZE);
+      }
+      encryptionContext.setMaxWrappedSize(maxWrappedSize);
+
+      logger.info("Configured bit-to-bit connections to require authentication using: {} with encryption: {}",
+          authMechanismToUse, encryptionContext.getEncryptionCtxtString());
+
+    } else if (config.getBoolean(ExecConstants.BIT_ENCRYPTION_SASL_ENABLED)) {
+      throw new DrillbitStartupException("Invalid security configuration. Encryption using SASL is enabled with " +
+          "authentication disabled. Please check the security.bit configurations.");
     } else {
       this.authMechanismToUse = null;
     }
@@ -78,7 +101,8 @@ public abstract class BitConnectionConfig extends AbstractConnectionConfig {
     return getAuthProvider().getAuthenticatorFactory(authMechanismToUse);
   }
 
-  public Map<String, ?> getSaslClientProperties(final DrillbitEndpoint remoteEndpoint) throws IOException {
+  public Map<String, ?> getSaslClientProperties(final DrillbitEndpoint remoteEndpoint,
+                                                final Map<String, String> overrides) throws IOException {
     final DrillProperties properties = DrillProperties.createEmpty();
 
     final UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
@@ -93,6 +117,8 @@ public abstract class BitConnectionConfig extends AbstractConnectionConfig {
         properties.setProperty(DrillProperties.SERVICE_PRINCIPAL, loginPrincipal.toString());
       }
     }
+
+    properties.merge(overrides);
     return properties.stringPropertiesAsMap();
   }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/ConnectionConfig.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/ConnectionConfig.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/ConnectionConfig.java
index 706b088..5b8a70b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/ConnectionConfig.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/ConnectionConfig.java
@@ -31,4 +31,7 @@ public interface ConnectionConfig {
 
   AuthenticatorProvider getAuthProvider();
 
+  boolean isEncryptionEnabled();
+
+  EncryptionContext getEncryptionCtxt();
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlClient.java
index 6ebe1c4..a46e968 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlClient.java
@@ -18,6 +18,8 @@
 package org.apache.drill.exec.rpc.control;
 
 import com.google.common.util.concurrent.SettableFuture;
+import com.google.protobuf.MessageLite;
+
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.socket.SocketChannel;
@@ -36,13 +38,14 @@ import org.apache.drill.exec.rpc.RpcCommand;
 import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
 import org.apache.drill.exec.rpc.FailingRequestHandler;
+import org.apache.drill.exec.rpc.security.SaslProperties;
 
-import com.google.protobuf.MessageLite;
 import org.apache.hadoop.security.UserGroupInformation;
 
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
 import java.io.IOException;
+import java.util.Map;
 import java.util.concurrent.ExecutionException;
 
 public class ControlClient extends BasicClient<RpcType, ControlConnection, BitControlHandshake, BitControlHandshake> {
@@ -105,9 +108,12 @@ public class ControlClient extends BasicClient<RpcType, ControlConnection, BitCo
     if (handshake.getAuthenticationMechanismsCount() != 0) { // remote requires authentication
       final SaslClient saslClient;
       try {
+        final Map<String, String> saslProperties = SaslProperties.getSaslProperties(connection.isEncryptionEnabled(),
+                                                                                    connection.getMaxWrappedSize());
+
         saslClient = config.getAuthFactory(handshake.getAuthenticationMechanismsList())
             .createSaslClient(UserGroupInformation.getLoginUser(),
-                config.getSaslClientProperties(remoteEndpoint));
+                config.getSaslClientProperties(remoteEndpoint, saslProperties));
       } catch (final IOException e) {
         throw new RpcException(String.format("Failed to initiate authenticate to %s", remoteEndpoint.getAddress()), e);
       }
@@ -118,7 +124,7 @@ public class ControlClient extends BasicClient<RpcType, ControlConnection, BitCo
     } else {
       if (config.getAuthMechanismToUse() != null) { // local requires authentication
         throw new RpcException(String.format("Drillbit (%s) does not require auth, but auth is enabled.",
-                remoteEndpoint.getAddress()));
+            remoteEndpoint.getAddress()));
       }
     }
   }
@@ -126,6 +132,9 @@ public class ControlClient extends BasicClient<RpcType, ControlConnection, BitCo
   @Override
   protected void finalizeConnection(BitControlHandshake handshake, ControlConnection connection) {
     connection.setEndpoint(handshake.getEndpoint());
+
+    // Increment the Control Connection counter.
+    connection.incConnectionCounter();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlConnection.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlConnection.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlConnection.java
index a50a3b0..70189d7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlConnection.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlConnection.java
@@ -18,15 +18,20 @@
 package org.apache.drill.exec.rpc.control;
 
 import com.google.protobuf.MessageLite;
+
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.socket.SocketChannel;
+
 import org.apache.drill.exec.proto.BitControl.RpcType;
 import org.apache.drill.exec.proto.CoordinationProtos.DrillbitEndpoint;
 import org.apache.drill.exec.rpc.AbstractServerConnection;
 import org.apache.drill.exec.rpc.ClientConnection;
 import org.apache.drill.exec.rpc.RequestHandler;
 import org.apache.drill.exec.rpc.RpcBus;
+import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
+import org.apache.drill.exec.rpc.SaslCodec;
+
 import org.slf4j.Logger;
 
 import javax.security.sasl.SaslClient;
@@ -115,6 +120,24 @@ public class ControlConnection extends AbstractServerConnection<ControlConnectio
   public void setSaslClient(final SaslClient saslClient) {
     checkState(this.saslClient == null);
     this.saslClient = saslClient;
+
+    // If encryption is enabled set the backend wrapper instance corresponding to this SaslClient in the connection
+    // object. This is later used to do wrap/unwrap in handlers.
+    if (isEncryptionEnabled()) {
+      saslCodec = new SaslCodec() {
+        @Override
+        public byte[] wrap(byte[] data, int offset, int len) throws SaslException {
+          assert saslClient != null;
+          return saslClient.wrap(data, offset, len);
+        }
+
+        @Override
+        public byte[] unwrap(byte[] data, int offset, int len) throws SaslException {
+          assert saslClient != null;
+          return saslClient.unwrap(data, offset, len);
+        }
+      };
+    }
   }
 
   @Override
@@ -124,7 +147,7 @@ public class ControlConnection extends AbstractServerConnection<ControlConnectio
   }
 
   @Override
-  public void close() {
+  public void disposeSaslClient() {
     try {
       if (saslClient != null) {
         saslClient.dispose();
@@ -133,7 +156,25 @@ public class ControlConnection extends AbstractServerConnection<ControlConnectio
     } catch (final SaslException e) {
       getLogger().warn("Unclean disposal", e);
     }
-    super.close();
   }
 
+  @Override
+  public void channelClosed(RpcException ex) {
+    // This will be triggered from Netty when a channel is closed. We should cleanup here
+    // as this will handle case for both client closing the connection or server closing the
+    // connection.
+    disposeSaslClient();
+
+    super.channelClosed(ex);
+  }
+
+  @Override
+  public void incConnectionCounter() {
+    ControlRpcMetrics.getInstance().addConnectionCount();
+  }
+
+  @Override
+  public void decConnectionCounter() {
+    ControlRpcMetrics.getInstance().decConnectionCount();
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlRpcMetrics.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlRpcMetrics.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlRpcMetrics.java
new file mode 100644
index 0000000..ae9e7cc
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlRpcMetrics.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc.control;
+
+import org.apache.drill.exec.memory.BufferAllocator;
+import org.apache.drill.exec.metrics.DrillMetrics;
+import org.apache.drill.exec.rpc.AbstractRpcMetrics;
+import com.codahale.metrics.Counter;
+import org.apache.drill.exec.rpc.RpcMetrics;
+
+/**
+ * Holds metrics related to bit control rpc layer
+ */
+class ControlRpcMetrics extends AbstractRpcMetrics {
+  //private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ControlRpcMetrics.class);
+
+  // Total number of control connection's as client and server for a DrillBit.
+  // i.e. Sum of incoming and outgoing control connections.
+  private static final Counter encryptedConnections = DrillMetrics.getRegistry()
+      .counter(CONNECTION_COUNTER_PREFIX + "control.encrypted");
+
+  private static final Counter unencryptedConnection = DrillMetrics.getRegistry()
+      .counter(CONNECTION_COUNTER_PREFIX + "control.unencrypted");
+
+  private static final RpcMetrics INSTANCE = new ControlRpcMetrics();
+
+  // prevent instantiation
+  private ControlRpcMetrics() {
+  }
+
+  public static RpcMetrics getInstance() {
+    return INSTANCE;
+  }
+
+  /**
+   * Should only be called when first access to getInstance is made. In this case inside {@link ControllerImpl}.
+   * {@link ControlConnection} using the singleton instance should not call initialize.
+   *
+   * @param useEncryptedCounter
+   * @param allocator
+   */
+  @Override
+  public void initialize(boolean useEncryptedCounter, BufferAllocator allocator) {
+    this.useEncryptedCounter = useEncryptedCounter;
+    registerAllocatorMetrics(allocator);
+  }
+
+  @Override
+  public void addConnectionCount() {
+    if (useEncryptedCounter) {
+      encryptedConnections.inc();
+    } else {
+      unencryptedConnection.inc();
+    }
+  }
+
+  @Override
+  public void decConnectionCount() {
+    if (useEncryptedCounter) {
+      encryptedConnections.dec();
+    } else {
+      unencryptedConnection.dec();
+    }
+  }
+
+  private void registerAllocatorMetrics(final BufferAllocator allocator) {
+    registerAllocatorMetrics(allocator, ALLOCATOR_METRICS_PREFIX + "bit.control.");
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlServer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlServer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlServer.java
index 9e733df..09f6705 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlServer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControlServer.java
@@ -17,10 +17,10 @@
  */
 package org.apache.drill.exec.rpc.control;
 
+import com.google.protobuf.MessageLite;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.GenericFutureListener;
-
 import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.proto.BitControl.BitControlHandshake;
 import org.apache.drill.exec.proto.BitControl.RpcType;
@@ -30,8 +30,6 @@ import org.apache.drill.exec.rpc.ProtobufLengthDecoder;
 import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.security.ServerAuthenticationHandler;
 
-import com.google.protobuf.MessageLite;
-
 public class ControlServer extends BasicServer<RpcType, ControlConnection>{
 //  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ControlServer.class);
 
@@ -105,6 +103,10 @@ public class ControlServer extends BasicServer<RpcType, ControlConnection>{
         if (config.getAuthMechanismToUse() != null) {
           builder.addAllAuthenticationMechanisms(config.getAuthProvider().getAllFactoryNames());
         }
+
+        // Increase the Control Connection counter on server side
+        connection.incConnectionCounter();
+
         return builder.build();
       }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControllerImpl.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControllerImpl.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControllerImpl.java
index 2bf5ad3..7ce2e97 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControllerImpl.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/control/ControllerImpl.java
@@ -48,6 +48,9 @@ public class ControllerImpl implements Controller {
     config = new ControlConnectionConfig(allocator, context, handler);
     this.connectionRegistry = new ConnectionManagerRegistry(config);
     this.handlerRegistry = handler.getHandlerRegistry();
+
+    // Initialize the singleton instance of ControlRpcMetrics.
+    ((ControlRpcMetrics)ControlRpcMetrics.getInstance()).initialize(config.isEncryptionEnabled(), allocator);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClient.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClient.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClient.java
index a37008d..603168d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClient.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClient.java
@@ -18,11 +18,11 @@
 package org.apache.drill.exec.rpc.data;
 
 import com.google.common.util.concurrent.SettableFuture;
+import com.google.protobuf.MessageLite;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.GenericFutureListener;
-
 import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.proto.BitData.BitClientHandshake;
 import org.apache.drill.exec.proto.BitData.BitServerHandshake;
@@ -34,15 +34,15 @@ import org.apache.drill.exec.rpc.ProtobufLengthDecoder;
 import org.apache.drill.exec.rpc.ResponseSender;
 import org.apache.drill.exec.rpc.RpcCommand;
 import org.apache.drill.exec.rpc.RpcException;
-import org.apache.drill.exec.rpc.security.AuthenticationOutcomeListener;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
-
-import com.google.protobuf.MessageLite;
+import org.apache.drill.exec.rpc.security.AuthenticationOutcomeListener;
+import org.apache.drill.exec.rpc.security.SaslProperties;
 import org.apache.hadoop.security.UserGroupInformation;
 
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
 import java.io.IOException;
+import java.util.Map;
 import java.util.concurrent.ExecutionException;
 
 public class DataClient extends BasicClient<RpcType, DataClientConnection, BitClientHandshake, BitServerHandshake> {
@@ -72,7 +72,7 @@ public class DataClient extends BasicClient<RpcType, DataClientConnection, BitCl
   @Override
   protected DataClientConnection initRemoteConnection(SocketChannel channel) {
     super.initRemoteConnection(channel);
-    this.connection = new DataClientConnection(channel, this);
+    this.connection = new DataClientConnection(channel, this, config.getEncryptionCtxt());
     return connection;
   }
 
@@ -107,9 +107,13 @@ public class DataClient extends BasicClient<RpcType, DataClientConnection, BitCl
     if (handshake.getAuthenticationMechanismsCount() != 0) { // remote requires authentication
       final SaslClient saslClient;
       try {
+
+        final Map<String, String> saslProperties = SaslProperties.getSaslProperties(connection.isEncryptionEnabled(),
+                                                                                    connection.getMaxWrappedSize());
+
         saslClient = config.getAuthFactory(handshake.getAuthenticationMechanismsList())
             .createSaslClient(UserGroupInformation.getLoginUser(),
-                config.getSaslClientProperties(remoteEndpoint));
+                config.getSaslClientProperties(remoteEndpoint, saslProperties));
       } catch (final IOException e) {
         throw new RpcException(String.format("Failed to initiate authenticate to %s", remoteEndpoint.getAddress()), e);
       }
@@ -126,6 +130,11 @@ public class DataClient extends BasicClient<RpcType, DataClientConnection, BitCl
   }
 
   @Override
+  protected void finalizeConnection(BitServerHandshake handshake, DataClientConnection connection) {
+    // Increment the Data Connection counter.
+    connection.incConnectionCounter();
+  }
+
   protected <M extends MessageLite> RpcCommand<M, DataClientConnection>
   getInitialCommand(final RpcCommand<M, DataClientConnection> command) {
     final RpcCommand<M, DataClientConnection> initialCommand = super.getInitialCommand(command);

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClientConnection.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClientConnection.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClientConnection.java
index 625ab25..6ada2f4 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClientConnection.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataClientConnection.java
@@ -25,6 +25,7 @@ import java.util.UUID;
 import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.proto.BitData.RpcType;
 import org.apache.drill.exec.rpc.AbstractClientConnection;
+import org.apache.drill.exec.rpc.EncryptionContext;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
 
 import com.google.protobuf.MessageLite;
@@ -37,8 +38,9 @@ public class DataClientConnection extends AbstractClientConnection {
   private final DataClient client;
   private final UUID id;
 
-  public DataClientConnection(SocketChannel channel, DataClient client) {
-    super(channel, "data client");
+  public DataClientConnection(SocketChannel channel, DataClient client,
+                              EncryptionContext encryptionContextImpl) {
+    super(channel, "data client", encryptionContextImpl);
     this.client = client;
     this.id = UUID.randomUUID();
   }
@@ -88,4 +90,14 @@ public class DataClientConnection extends AbstractClientConnection {
   protected Logger getLogger() {
     return logger;
   }
+
+  @Override
+  public void incConnectionCounter() {
+    DataRpcMetrics.getInstance().addConnectionCount();
+  }
+
+  @Override
+  public void decConnectionCounter() {
+    DataRpcMetrics.getInstance().decConnectionCount();
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataConnectionCreator.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataConnectionCreator.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataConnectionCreator.java
index 25c83b3..27b2250 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataConnectionCreator.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataConnectionCreator.java
@@ -44,6 +44,9 @@ public class DataConnectionCreator implements AutoCloseable {
   public DataConnectionCreator(BootStrapContext context, BufferAllocator allocator, WorkEventBus workBus,
                                WorkerBee bee) throws DrillbitStartupException {
     config = new DataConnectionConfig(allocator, context, new DataServerRequestHandler(workBus, bee));
+
+    // Initialize the singleton instance of DataRpcMetrics.
+    ((DataRpcMetrics) DataRpcMetrics.getInstance()).initialize(config.isEncryptionEnabled(), allocator);
   }
 
   public DrillbitEndpoint start(DrillbitEndpoint partialEndpoint, boolean allowPortHunting) {
@@ -59,7 +62,7 @@ public class DataConnectionCreator implements AutoCloseable {
   public DataTunnel getTunnel(DrillbitEndpoint endpoint) {
     DataConnectionManager newManager = new DataConnectionManager(endpoint, config);
     DataConnectionManager oldManager = connectionManager.putIfAbsent(endpoint, newManager);
-    if(oldManager != null){
+    if (oldManager != null) {
       newManager = oldManager;
     }
     return new DataTunnel(newManager);

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataRpcMetrics.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataRpcMetrics.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataRpcMetrics.java
new file mode 100644
index 0000000..997df57
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataRpcMetrics.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc.data;
+
+import com.codahale.metrics.Counter;
+import org.apache.drill.exec.memory.BufferAllocator;
+import org.apache.drill.exec.metrics.DrillMetrics;
+import org.apache.drill.exec.rpc.AbstractRpcMetrics;
+import org.apache.drill.exec.rpc.RpcMetrics;
+
+/**
+ * Holds metrics related to bit data rpc layer
+ */
+class DataRpcMetrics extends AbstractRpcMetrics {
+  //private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DataRpcMetrics.class);
+
+  // Total number of data connection's as client and server for a DrillBit.
+  // i.e. Sum of incoming and outgoing data connections.
+  private static final Counter encryptedConnections = DrillMetrics.getRegistry()
+      .counter(CONNECTION_COUNTER_PREFIX + "data.encrypted");
+
+  private static final Counter unencryptedConnection = DrillMetrics.getRegistry()
+      .counter(CONNECTION_COUNTER_PREFIX + "data.unencrypted");
+
+  private static final RpcMetrics INSTANCE = new DataRpcMetrics();
+
+  // prevent instantiation
+  private DataRpcMetrics() {
+  }
+
+  public static RpcMetrics getInstance() {
+    return INSTANCE;
+  }
+
+  /**
+   * Should only be called when first access to getInstance is made. In this case inside {@link DataConnectionCreator}.
+   * {@link DataServerConnection} and {@link DataClientConnection} using the singleton instance should not call
+   * initialize.
+   *
+   * @param useEncryptedCounter
+   * @param allocator
+   */
+  @Override
+  public void initialize(boolean useEncryptedCounter, BufferAllocator allocator) {
+    this.useEncryptedCounter = useEncryptedCounter;
+    registerAllocatorMetrics(allocator);
+  }
+
+  @Override
+  public void addConnectionCount() {
+    if (useEncryptedCounter) {
+      encryptedConnections.inc();
+    } else {
+      unencryptedConnection.inc();
+    }
+  }
+
+  @Override
+  public void decConnectionCount() {
+    if (useEncryptedCounter) {
+      encryptedConnections.dec();
+    } else {
+      unencryptedConnection.dec();
+    }
+  }
+
+  private void registerAllocatorMetrics(final BufferAllocator allocator) {
+    registerAllocatorMetrics(allocator, ALLOCATOR_METRICS_PREFIX + "bit.data.");
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServer.java
index 33270fd..9e31d6b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServer.java
@@ -17,10 +17,10 @@
  */
 package org.apache.drill.exec.rpc.data;
 
+import com.google.protobuf.MessageLite;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.util.concurrent.GenericFutureListener;
-
 import org.apache.drill.exec.memory.BufferAllocator;
 import org.apache.drill.exec.proto.BitData.BitClientHandshake;
 import org.apache.drill.exec.proto.BitData.BitServerHandshake;
@@ -31,8 +31,6 @@ import org.apache.drill.exec.rpc.OutOfMemoryHandler;
 import org.apache.drill.exec.rpc.ProtobufLengthDecoder;
 import org.apache.drill.exec.rpc.RpcException;
 
-import com.google.protobuf.MessageLite;
-
 public class DataServer extends BasicServer<RpcType, DataServerConnection> {
   private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DataServer.class);
 
@@ -84,6 +82,10 @@ public class DataServer extends BasicServer<RpcType, DataServerConnection> {
         if (config.getAuthMechanismToUse() != null) {
           builder.addAllAuthenticationMechanisms(config.getAuthProvider().getAllFactoryNames());
         }
+
+        // Increase the Data Connection counter on server side.
+        connection.incConnectionCounter();
+
         return builder.build();
       }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServerConnection.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServerConnection.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServerConnection.java
index 70e262f..41a4b1c 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServerConnection.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/data/DataServerConnection.java
@@ -39,4 +39,13 @@ public class DataServerConnection extends AbstractServerConnection<DataServerCon
     return logger;
   }
 
+  @Override
+  public void incConnectionCounter() {
+    DataRpcMetrics.getInstance().addConnectionCount();
+  }
+
+  @Override
+  public void decConnectionCounter() {
+    DataRpcMetrics.getInstance().decConnectionCount();
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticationOutcomeListener.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticationOutcomeListener.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticationOutcomeListener.java
index 9c74ddc..7f51142 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticationOutcomeListener.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticationOutcomeListener.java
@@ -31,6 +31,7 @@ import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.RpcOutcomeListener;
 import org.apache.hadoop.security.UserGroupInformation;
 
+import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
 import java.io.IOException;
@@ -55,7 +56,8 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
   private static final org.slf4j.Logger logger =
       org.slf4j.LoggerFactory.getLogger(AuthenticationOutcomeListener.class);
 
-  private static final ImmutableMap<SaslStatus, SaslChallengeProcessor> CHALLENGE_PROCESSORS;
+  private static final ImmutableMap<SaslStatus, SaslChallengeProcessor>
+      CHALLENGE_PROCESSORS;
   static {
     final Map<SaslStatus, SaslChallengeProcessor> map = new EnumMap<>(SaslStatus.class);
     map.put(SaslStatus.SASL_IN_PROGRESS, new SaslInProgressProcessor());
@@ -99,7 +101,7 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
               .setData(responseData)
               .build(),
           SaslMessage.class,
-          true /** the connection will not be backed up at this point */);
+          true /* the connection will not be backed up at this point */);
       logger.trace("Initiated SASL exchange.");
     } catch (final Exception e) {
       completionListener.failed(RpcException.mapException(e));
@@ -120,19 +122,24 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
           new SaslException("Server sent a corrupt message.")));
     } else {
       try {
-        final SaslChallengeContext context = new SaslChallengeContext(value, connection.getSaslClient(), ugi);
-
+        final SaslChallengeContext<C> context = new SaslChallengeContext<>(value, ugi, connection);
         final SaslMessage saslResponse = processor.process(context);
 
         if (saslResponse != null) {
           client.send(new AuthenticationOutcomeListener<>(client, connection, saslRpcType, ugi, completionListener),
               connection, saslRpcType, saslResponse, SaslMessage.class,
-              true /** the connection will not be backed up at this point */);
+              true /* the connection will not be backed up at this point */);
         } else {
           // success
           completionListener.success(null, null);
+          if (logger.isTraceEnabled()) {
+            logger.trace("Successfully authenticated to server using {} mechanism and encryption context: {}",
+                connection.getSaslClient().getMechanismName(), connection.getEncryptionCtxtString());
+          }
         }
       } catch (final Exception e) {
+        logger.error("Authentication with encryption context: {} using mechanism {} failed with {}",
+            connection.getEncryptionCtxtString(), connection.getSaslClient().getMechanismName(), e.getMessage());
         completionListener.failed(RpcException.mapException(e));
       }
     }
@@ -143,16 +150,16 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
     completionListener.interrupted(e);
   }
 
-  private static class SaslChallengeContext {
+  private static class SaslChallengeContext<C extends ClientConnection> {
 
     final SaslMessage challenge;
-    final SaslClient saslClient;
     final UserGroupInformation ugi;
+    final C connection;
 
-    SaslChallengeContext(SaslMessage challenge, SaslClient saslClient, UserGroupInformation ugi) {
+    SaslChallengeContext(SaslMessage challenge, UserGroupInformation ugi, C connection) {
       this.challenge = checkNotNull(challenge);
-      this.saslClient = checkNotNull(saslClient);
       this.ugi = checkNotNull(ugi);
+      this.connection = checkNotNull(connection);
     }
   }
 
@@ -165,22 +172,24 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
      *
      * @param context challenge context
      * @return response
-     * @throws Exception
+     * @throws Exception in case of any failure
      */
-    SaslMessage process(SaslChallengeContext context) throws Exception;
+    <CC extends ClientConnection>
+    SaslMessage process(SaslChallengeContext<CC> context) throws Exception;
 
   }
 
   private static class SaslInProgressProcessor implements SaslChallengeProcessor {
 
     @Override
-    public SaslMessage process(SaslChallengeContext context) throws Exception {
+    public <CC extends ClientConnection> SaslMessage process(SaslChallengeContext<CC> context) throws Exception {
       final SaslMessage.Builder response = SaslMessage.newBuilder();
+      final SaslClient saslClient = context.connection.getSaslClient();
 
-      final byte[] responseBytes = evaluateChallenge(context.ugi, context.saslClient,
+      final byte[] responseBytes = evaluateChallenge(context.ugi, saslClient,
           context.challenge.getData().toByteArray());
 
-      final boolean isComplete = context.saslClient.isComplete();
+      final boolean isComplete = saslClient.isComplete();
       logger.trace("Evaluated challenge. Completed? {}.", isComplete);
       response.setData(responseBytes != null ? ByteString.copyFrom(responseBytes) : ByteString.EMPTY);
       // if isComplete, the client will get one more response from server
@@ -192,20 +201,18 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
   private static class SaslSuccessProcessor implements SaslChallengeProcessor {
 
     @Override
-    public SaslMessage process(SaslChallengeContext context) throws Exception {
-      if (context.saslClient.isComplete()) {
-        logger.trace("Successfully authenticated to server using {}", context.saslClient.getMechanismName());
-        // setup security layers here..
+    public <CC extends ClientConnection> SaslMessage process(SaslChallengeContext<CC> context) throws Exception {
+      final SaslClient saslClient = context.connection.getSaslClient();
+
+      if (saslClient.isComplete()) {
+        handleSuccess(context);
         return null;
       } else {
-
         // server completed before client; so try once, fail otherwise
-        evaluateChallenge(context.ugi, context.saslClient,
-            context.challenge.getData().toByteArray()); // discard response
+        evaluateChallenge(context.ugi, saslClient, context.challenge.getData().toByteArray()); // discard response
 
-        if (context.saslClient.isComplete()) {
-          logger.trace("Successfully authenticated to server using {}", context.saslClient.getMechanismName());
-          // setup security layers here..
+        if (saslClient.isComplete()) {
+          handleSuccess(context);
           return null;
         } else {
           throw new SaslException("Server allegedly succeeded authentication, but client did not. Suspicious?");
@@ -217,8 +224,9 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
   private static class SaslFailedProcessor implements SaslChallengeProcessor {
 
     @Override
-    public SaslMessage process(SaslChallengeContext context) throws Exception {
-      throw new SaslException("Authentication failed. Incorrect credentials?");
+    public <CC extends ClientConnection> SaslMessage process(SaslChallengeContext<CC> context) throws Exception {
+      throw new SaslException(String.format("Authentication failed. Incorrect credentials? [Details: %s]",
+          context.connection.getEncryptionCtxtString()));
     }
   }
 
@@ -243,4 +251,48 @@ public class AuthenticationOutcomeListener<T extends EnumLite, C extends ClientC
       }
     }
   }
+
+
+  private static <CC extends ClientConnection> void handleSuccess(SaslChallengeContext<CC> context) throws
+      SaslException {
+    final CC connection = context.connection;
+    final SaslClient saslClient = connection.getSaslClient();
+
+    try {
+      // Check if connection was marked for being secure then verify for negotiated QOP value for
+      // correctness.
+      final String negotiatedQOP = saslClient.getNegotiatedProperty(Sasl.QOP).toString();
+      final String expectedQOP = connection.isEncryptionEnabled()
+          ? SaslProperties.QualityOfProtection.PRIVACY.getSaslQop()
+          : SaslProperties.QualityOfProtection.AUTHENTICATION.getSaslQop();
+
+      if (!(negotiatedQOP.equals(expectedQOP))) {
+        throw new SaslException(String.format("Mismatch in negotiated QOP value: %s and Expected QOP value: %s",
+            negotiatedQOP, expectedQOP));
+      }
+
+      // Update the rawWrapChunkSize with the negotiated buffer size since we cannot call encode with more than
+      // negotiated size of buffer.
+      if (connection.isEncryptionEnabled()) {
+        final int negotiatedRawSendSize = Integer.parseInt(
+            saslClient.getNegotiatedProperty(Sasl.RAW_SEND_SIZE).toString());
+        if (negotiatedRawSendSize <= 0) {
+          throw new SaslException(String.format("Negotiated rawSendSize: %d is invalid. Please check the configured " +
+              "value of encryption.sasl.max_wrapped_size. It might be configured to a very small value.",
+              negotiatedRawSendSize));
+        }
+        connection.setWrapSizeLimit(negotiatedRawSendSize);
+      }
+    } catch (Exception e) {
+      throw new SaslException(String.format("Unexpected failure while retrieving negotiated property values (%s)",
+          e.getMessage()), e);
+    }
+
+    if (connection.isEncryptionEnabled()) {
+      connection.addSecurityHandlers();
+    } else {
+      // Encryption is not required hence we don't need to hold on to saslClient object.
+      connection.disposeSaslClient();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticatorProviderImpl.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticatorProviderImpl.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticatorProviderImpl.java
index f4c60e7..cfb9512 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticatorProviderImpl.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/AuthenticatorProviderImpl.java
@@ -137,5 +137,4 @@ public class AuthenticatorProviderImpl implements AuthenticatorProvider {
     AutoCloseables.close(authFactories.values());
     authFactories.clear();
   }
-
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ClientAuthenticatorProvider.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ClientAuthenticatorProvider.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ClientAuthenticatorProvider.java
index bdcbcf5..5cac208 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ClientAuthenticatorProvider.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ClientAuthenticatorProvider.java
@@ -48,7 +48,7 @@ public class ClientAuthenticatorProvider implements AuthenticatorProvider {
   // Mapping: simple name -> authenticator factory
   private final Map<String, AuthenticatorFactory> authFactories = CaseInsensitiveMap.newHashMapWithExpectedSize(5);
 
-  public ClientAuthenticatorProvider() {
+  private ClientAuthenticatorProvider() {
     // factories provided by Drill
     final KerberosFactory kerberosFactory = new KerberosFactory();
     authFactories.put(kerberosFactory.getSimpleName(), kerberosFactory);

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/SaslProperties.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/SaslProperties.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/SaslProperties.java
new file mode 100644
index 0000000..9ed85ce
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/SaslProperties.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.rpc.security;
+
+import javax.security.sasl.Sasl;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class SaslProperties {
+
+  /**
+   * All supported Quality of Protection values which can be negotiated
+   */
+  enum QualityOfProtection {
+    AUTHENTICATION("auth"),
+    INTEGRITY("auth-int"),
+    PRIVACY("auth-conf");
+
+    public final String saslQop;
+
+    QualityOfProtection(String saslQop) {
+      this.saslQop = saslQop;
+    }
+
+    public String getSaslQop() {
+      return saslQop;
+    }
+  }
+
+  /**
+   * Get's the map of minimum set of SaslProperties required during negotiation process either for encryption
+   * or authentication
+   * @param encryptionEnabled - Flag to determine if property needed is for encryption or authentication
+   * @param wrappedChunkSize  - Configured wrappedChunkSize to negotiate for.
+   * @return Map of SaslProperties which will be used in negotiation.
+   */
+  public static Map<String, String> getSaslProperties(boolean encryptionEnabled, int wrappedChunkSize) {
+    Map<String, String> saslProps = new HashMap<>();
+
+    if (encryptionEnabled) {
+      saslProps.put(Sasl.STRENGTH, "high");
+      saslProps.put(Sasl.QOP, QualityOfProtection.PRIVACY.getSaslQop());
+      saslProps.put(Sasl.MAX_BUFFER, Integer.toString(wrappedChunkSize));
+      saslProps.put(Sasl.POLICY_NOPLAINTEXT, "true");
+    } else {
+      saslProps.put(Sasl.QOP, QualityOfProtection.AUTHENTICATION.getSaslQop());
+    }
+
+    return saslProps;
+  }
+
+  private SaslProperties() {
+
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ServerAuthenticationHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ServerAuthenticationHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ServerAuthenticationHandler.java
index bf34d57..ddd216f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ServerAuthenticationHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/ServerAuthenticationHandler.java
@@ -33,6 +33,7 @@ import org.apache.drill.exec.rpc.RpcException;
 import org.apache.drill.exec.rpc.ServerConnection;
 import org.apache.hadoop.security.UserGroupInformation;
 
+import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 import java.io.IOException;
@@ -87,7 +88,7 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
       try {
         saslResponse = SaslMessage.PARSER.parseFrom(new ByteBufInputStream(pBody));
       } catch (final InvalidProtocolBufferException e) {
-        handleAuthFailure(remoteAddress, sender, e, saslResponseType);
+        handleAuthFailure(connection, sender, e, saslResponseType);
         return;
       }
 
@@ -95,17 +96,17 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
       final SaslResponseProcessor processor = RESPONSE_PROCESSORS.get(saslResponse.getStatus());
       if (processor == null) {
         logger.info("Unknown message type from client from {}. Will stop authentication.", remoteAddress);
-        handleAuthFailure(remoteAddress, sender, new SaslException("Received unexpected message"),
+        handleAuthFailure(connection, sender, new SaslException("Received unexpected message"),
             saslResponseType);
         return;
       }
 
-      final SaslResponseContext<S, T> context = new SaslResponseContext<>(saslResponse, connection, remoteAddress,
-          sender, requestHandler, saslResponseType);
+      final SaslResponseContext<S, T> context = new SaslResponseContext<>(saslResponse, connection, sender,
+          requestHandler, saslResponseType);
       try {
         processor.process(context);
       } catch (final Exception e) {
-        handleAuthFailure(remoteAddress, sender, e, saslResponseType);
+        handleAuthFailure(connection, sender, e, saslResponseType);
       }
     } else {
 
@@ -115,9 +116,9 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
       // but the client should not be making any requests before authenticating.
       // drop connection
       throw new RpcException(
-          String.format("Request of type %d is not allowed without authentication. " +
-                  "Client on %s must authenticate before making requests. Connection dropped.",
-              rpcType, remoteAddress));
+          String.format("Request of type %d is not allowed without authentication. Client on %s must authenticate " +
+              "before making requests. Connection dropped. [Details: %s]",
+              rpcType, remoteAddress, connection.getEncryptionCtxtString()));
     }
   }
 
@@ -125,16 +126,14 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
 
     final SaslMessage saslResponse;
     final S connection;
-    final String remoteAddress;
     final ResponseSender sender;
     final RequestHandler<S> requestHandler;
     final T saslResponseType;
 
-    SaslResponseContext(SaslMessage saslResponse, S connection, String remoteAddress, ResponseSender sender,
+    SaslResponseContext(SaslMessage saslResponse, S connection, ResponseSender sender,
                         RequestHandler<S> requestHandler, T saslResponseType) {
       this.saslResponse = checkNotNull(saslResponse);
       this.connection = checkNotNull(connection);
-      this.remoteAddress = checkNotNull(remoteAddress);
       this.sender = checkNotNull(sender);
       this.requestHandler = checkNotNull(requestHandler);
       this.saslResponseType = checkNotNull(saslResponseType);
@@ -208,8 +207,11 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
 
         handleSuccess(context, challenge, saslServer);
       } else {
-        logger.info("Failed to authenticate client from {}", context.remoteAddress);
-        throw new SaslException("Client allegedly succeeded authentication, but server did not. Suspicious?");
+        final S connection = context.connection;
+        logger.info("Failed to authenticate client from {} with encryption context:{}",
+            connection.getRemoteAddress().toString(), connection.getEncryptionCtxtString());
+        throw new SaslException(String.format("Client allegedly succeeded authentication but server did not. " +
+            "Suspicious? [Details: %s]", connection.getEncryptionCtxtString()));
       }
     }
   }
@@ -219,9 +221,11 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
     @Override
     public <S extends ServerConnection<S>, T extends EnumLite>
     void process(SaslResponseContext<S, T> context) throws Exception {
-      logger.info("Client from {} failed authentication graciously, and does not want to continue.",
-          context.remoteAddress);
-      throw new SaslException("Client graciously failed authentication");
+      final S connection = context.connection;
+      logger.info("Client from {} failed authentication with encryption context:{} graciously, and does not want to " +
+          "continue.", connection.getRemoteAddress().toString(), connection.getEncryptionCtxtString());
+      throw new SaslException(String.format("Client graciously failed authentication. [Details: %s]",
+          connection.getEncryptionCtxtString()));
     }
   }
 
@@ -251,25 +255,67 @@ public class ServerAuthenticationHandler<S extends ServerConnection<S>, T extend
   private static <S extends ServerConnection<S>, T extends EnumLite>
   void handleSuccess(final SaslResponseContext<S, T> context, final SaslMessage.Builder challenge,
                      final SaslServer saslServer) throws IOException {
-    context.connection.changeHandlerTo(context.requestHandler);
-    context.connection.finalizeSaslSession();
-    context.sender.send(new Response(context.saslResponseType, challenge.build()));
 
-    // setup security layers here..
+    final S connection = context.connection;
+    connection.changeHandlerTo(context.requestHandler);
+    connection.finalizeSaslSession();
+
+    // Check the negotiated property before sending the response back to client
+    try {
+      final String negotiatedQOP = saslServer.getNegotiatedProperty(Sasl.QOP).toString();
+      final String expectedQOP = (connection.isEncryptionEnabled())
+          ? SaslProperties.QualityOfProtection.PRIVACY.getSaslQop()
+          : SaslProperties.QualityOfProtection.AUTHENTICATION.getSaslQop();
+
+      if (!(negotiatedQOP.equals(expectedQOP))) {
+        throw new SaslException(String.format("Mismatch in negotiated QOP value: %s and Expected QOP value: %s",
+            negotiatedQOP, expectedQOP));
+      }
+
+      // Update the rawWrapSendSize with the negotiated rawSendSize since we cannot call encode with more than the
+      // negotiated size of buffer
+      if (connection.isEncryptionEnabled()) {
+        final int negotiatedRawSendSize = Integer.parseInt(
+            saslServer.getNegotiatedProperty(Sasl.RAW_SEND_SIZE).toString());
+        if (negotiatedRawSendSize <= 0) {
+          throw new SaslException(String.format("Negotiated rawSendSize: %d is invalid. Please check the configured " +
+              "value of encryption.sasl.max_wrapped_size. It might be configured to a very small value.",
+              negotiatedRawSendSize));
+        }
+        connection.setWrapSizeLimit(negotiatedRawSendSize);
+      }
+    } catch (IllegalStateException | NumberFormatException e) {
+      throw new SaslException(String.format("Unexpected failure while retrieving negotiated property values (%s)",
+          e.getMessage()), e);
+    }
 
     if (logger.isTraceEnabled()) {
-      logger.trace("Authenticated {} successfully using {} from {}", saslServer.getAuthorizationID(),
-          saslServer.getMechanismName(), context.remoteAddress);
+      logger.trace("Authenticated {} successfully using {} from {} with encryption context {}",
+          saslServer.getAuthorizationID(), saslServer.getMechanismName(), connection.getRemoteAddress().toString(),
+          connection.getEncryptionCtxtString());
+    }
+
+    // All checks have passed let's send the response back to client before adding handlers.
+    context.sender.send(new Response(context.saslResponseType, challenge.build()));
+
+    if (connection.isEncryptionEnabled()) {
+      connection.addSecurityHandlers();
+    } else {
+      // Encryption is not required hence we don't need to hold on to saslServer object.
+      connection.disposeSaslServer();
     }
   }
 
   private static final SaslMessage SASL_FAILED_MESSAGE =
       SaslMessage.newBuilder().setStatus(SaslStatus.SASL_FAILED).build();
 
-  private static <T extends EnumLite>
-  void handleAuthFailure(final String remoteAddress, final ResponseSender sender,
+  private static <S extends ServerConnection<S>, T extends EnumLite>
+  void handleAuthFailure(final S connection, final ResponseSender sender,
                          final Exception e, final T saslResponseType) throws RpcException {
-    logger.debug("Authentication failed from client {} due to {}", remoteAddress, e);
+    final String remoteAddress = connection.getRemoteAddress().toString();
+
+    logger.debug("Authentication using mechanism {} with encryption context {} failed from client {} due to {}",
+        connection.getSaslServer().getMechanismName(), connection.getEncryptionCtxtString(), remoteAddress, e);
 
     // inform the client that authentication failed, and no more
     sender.send(new Response(saslResponseType, SASL_FAILED_MESSAGE));

http://git-wip-us.apache.org/repos/asf/drill/blob/ce8bbc01/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/kerberos/KerberosFactory.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/kerberos/KerberosFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/kerberos/KerberosFactory.java
index 855dd8b..e14d411 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/kerberos/KerberosFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/security/kerberos/KerberosFactory.java
@@ -33,6 +33,7 @@ import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginException;
 import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
@@ -93,6 +94,7 @@ public class KerberosFactory implements AuthenticatorFactory {
   @Override
   public SaslServer createSaslServer(final UserGroupInformation ugi, final Map<String, ?> properties)
       throws SaslException {
+    final String qopValue = properties.containsKey(Sasl.QOP) ? properties.get(Sasl.QOP).toString() : "auth";
     try {
       final String primaryName = ugi.getShortUserName();
       final String instanceName = new HadoopKerberosName(ugi.getUserName()).getHostName();
@@ -105,7 +107,7 @@ public class KerberosFactory implements AuthenticatorFactory {
                   new KerberosServerCallbackHandler());
         }
       });
-      logger.trace("GSSAPI SaslServer created.");
+      logger.trace("GSSAPI SaslServer created with QOP {}.", qopValue);
       return saslServer;
     } catch (final UndeclaredThrowableException e) {
       final Throwable cause = e.getCause();
@@ -113,11 +115,13 @@ public class KerberosFactory implements AuthenticatorFactory {
       if (cause instanceof SaslException) {
         throw (SaslException) cause;
       } else {
-        throw new SaslException("Unexpected failure trying to authenticate using Kerberos", cause);
+        throw new SaslException(String.format("Unexpected failure trying to authenticate using Kerberos with QOP %s",
+            qopValue), cause);
       }
     } catch (final IOException | InterruptedException e) {
       logger.debug("Authentication failed.", e);
-      throw new SaslException("Unexpected failure trying to authenticate using Kerberos", e);
+      throw new SaslException(String.format("Unexpected failure trying to authenticate using Kerberos with QOP %s",
+          qopValue), e);
     }
   }
 
@@ -129,6 +133,8 @@ public class KerberosFactory implements AuthenticatorFactory {
     final String parts[] = KerberosUtil.splitPrincipalIntoParts(servicePrincipal);
     final String serviceName = parts[0];
     final String serviceHostName = parts[1];
+    final String qopValue = properties.containsKey(Sasl.QOP) ? properties.get(Sasl.QOP).toString() : "auth";
+
     // ignore parts[2]; GSSAPI gets the realm info from the ticket
     try {
       final SaslClient saslClient = ugi.doAs(new PrivilegedExceptionAction<SaslClient>() {
@@ -146,20 +152,20 @@ public class KerberosFactory implements AuthenticatorFactory {
               });
         }
       });
-      logger.debug("GSSAPI SaslClient created to authenticate to {} running on {}",
-          serviceName, serviceHostName);
+      logger.debug("GSSAPI SaslClient created to authenticate to {} running on {} with QOP value {}",
+          serviceName, serviceHostName, qopValue);
       return saslClient;
     } catch (final UndeclaredThrowableException e) {
       logger.debug("Authentication failed.", e);
-      throw new SaslException(String.format("Unexpected failure trying to authenticate to %s using GSSAPI",
-          serviceHostName), e.getCause());
+      throw new SaslException(String.format("Unexpected failure trying to authenticate to %s using GSSAPI with QOP %s",
+          serviceHostName, qopValue), e.getCause());
     } catch (final IOException | InterruptedException e) {
       logger.debug("Authentication failed.", e);
       if (e instanceof SaslException) {
         throw (SaslException) e;
       }
-      throw new SaslException(String.format("Unexpected failure trying to authenticate to %s using GSSAPI",
-          serviceHostName), e);
+      throw new SaslException(String.format("Unexpected failure trying to authenticate to %s using GSSAPI with QOP %s",
+          serviceHostName, qopValue), e);
     }
   }
 


[6/6] drill git commit: DRILL-4335: Apache Drill should support network encryption.

Posted by am...@apache.org.
DRILL-4335: Apache Drill should support network encryption.

NOTE: This pull request provides support for on-wire encryption using SASL framework. Communication channel covered is:
      1) C++ Drill Client and Drillbit channel.

close apache/drill#809


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/d11aba2e
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/d11aba2e
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/d11aba2e

Branch: refs/heads/master
Commit: d11aba2e55323bb5a6a9deb5bb09fd87470dcedf
Parents: ce8bbc0
Author: Sorabh Hamirwasia <sh...@maprtech.com>
Authored: Mon Mar 6 00:19:50 2017 -0800
Committer: Aman Sinha <as...@maprtech.com>
Committed: Sat May 20 16:17:19 2017 -0700

----------------------------------------------------------------------
 .../native/client/example/querySubmitter.cpp    |  25 +-
 contrib/native/client/readme.macos              |   6 +-
 .../native/client/src/clientlib/drillClient.cpp |   1 +
 .../client/src/clientlib/drillClientImpl.cpp    | 694 ++++++++++++++++---
 .../client/src/clientlib/drillClientImpl.hpp    |  41 +-
 .../native/client/src/clientlib/rpcMessage.cpp  |   2 +-
 .../native/client/src/clientlib/rpcMessage.hpp  |   1 -
 .../src/clientlib/saslAuthenticatorImpl.cpp     | 119 +++-
 .../src/clientlib/saslAuthenticatorImpl.hpp     |  12 +-
 contrib/native/client/src/clientlib/utils.cpp   |  49 ++
 contrib/native/client/src/clientlib/utils.hpp   |  32 +
 .../native/client/src/include/drill/common.hpp  |   2 +
 contrib/native/client/src/protobuf/User.pb.cc   | 463 ++++++++-----
 contrib/native/client/src/protobuf/User.pb.h    |  71 +-
 14 files changed, 1194 insertions(+), 324 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/example/querySubmitter.cpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/example/querySubmitter.cpp b/contrib/native/client/example/querySubmitter.cpp
index 5990897..47e55de 100644
--- a/contrib/native/client/example/querySubmitter.cpp
+++ b/contrib/native/client/example/querySubmitter.cpp
@@ -1,3 +1,4 @@
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -24,7 +25,7 @@
 #include <boost/algorithm/string/join.hpp>
 #include "drill/drillc.hpp"
 
-int nOptions=15;
+int nOptions=19;
 
 struct Option{
     char name[32];
@@ -45,7 +46,11 @@ struct Option{
     {"heartbeatFrequency", "Heartbeat frequency (second). Disabled if set to 0.", false},
     {"user", "Username", false},
     {"password", "Password", false},
-    {"saslPluginPath", "Path to where SASL plugins are installed", false}
+    {"saslPluginPath", "Path to where SASL plugins are installed", false},
+    {"service_host", "Service host for Kerberos", false},
+    {"service_name", "Service name for Kerberos", false},
+    {"auth", "Authentication mechanism to use", false},
+    {"sasl_encrypt", "Negotiate for encrypted connection", false}
 };
 
 std::map<std::string, std::string> qsOptionValues;
@@ -295,6 +300,10 @@ int main(int argc, char* argv[]) {
         std::string user=qsOptionValues["user"];
         std::string password=qsOptionValues["password"];
         std::string saslPluginPath=qsOptionValues["saslPluginPath"];
+        std::string sasl_encrypt=qsOptionValues["sasl_encrypt"];
+        std::string serviceHost=qsOptionValues["service_host"];
+        std::string serviceName=qsOptionValues["service_name"];
+        std::string auth=qsOptionValues["auth"];
 
         Drill::QueryType type;
 
@@ -371,6 +380,18 @@ int main(int argc, char* argv[]) {
         if(password.length()>0){
             props.setProperty(USERPROP_PASSWORD, password);
         }
+        if(sasl_encrypt.length()>0){
+            props.setProperty(USERPROP_SASL_ENCRYPT, sasl_encrypt);
+        }
+        if(serviceHost.length()>0){
+            props.setProperty(USERPROP_SERVICE_HOST, serviceHost);
+        }
+        if(serviceName.length()>0){
+            props.setProperty(USERPROP_SERVICE_NAME, serviceName);
+        }
+        if(auth.length()>0){
+            props.setProperty(USERPROP_AUTH_MECHANISM, auth);
+        }
 
         if(client.connect(connectStr.c_str(), &props)!=Drill::CONN_SUCCESS){
             std::cerr<< "Failed to connect with error: "<< client.getError() << " (Using:"<<connectStr<<")"<<std::endl;

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/readme.macos
----------------------------------------------------------------------
diff --git a/contrib/native/client/readme.macos b/contrib/native/client/readme.macos
index 4785e87..eee017e 100644
--- a/contrib/native/client/readme.macos
+++ b/contrib/native/client/readme.macos
@@ -35,6 +35,8 @@ Install Prerequisites
   or use brew to install 
   $> brew install cmake
 
+2.0) Install cppunit 
+  $> brew install cppunit 
 
 2.1) Install protobuf 2.5.0 (or higher)
   $> brew install protobuf
@@ -54,7 +56,7 @@ Install Prerequisites
 When changes have been introduced to the protocol module, you might need to refresh the protobuf C++ source files too.
   $> cd DRILL_DIR/contrib/native/client
   $> mkdir build
-  $> cd build && cmake3 -G "XCode" -D CMAKE_BUILD_TYPE=Debug ..
+  $> cd build && cmake -G "Xcode" -D CMAKE_BUILD_TYPE=Debug ..
   $> xcodebuild -project drillclient.xcodeproj -configuration ${BUILDTYPE} -target fixProtobufs
   $> xcodebuild -project drillclient.xcodeproj -configuration ${BUILDTYPE} -target cpProtobufs
 
@@ -64,7 +66,7 @@ Build drill client
 -------------------
   $> cd DRILL_DIR/contrib/native/client
   $> mkdir build
-  $> cd build && cmake3 -G "XCode" -D CMAKE_BUILD_TYPE=Debug ..
+  $> cd build && cmake -G "Xcode" -D CMAKE_BUILD_TYPE=Debug ..
   $> xcodebuild -project drillclient.xcodeproj -configuration ${BUILDTYPE} -target ALL_BUILD
 
 

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/drillClient.cpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/drillClient.cpp b/contrib/native/client/src/clientlib/drillClient.cpp
index 7000272..8eb909b 100644
--- a/contrib/native/client/src/clientlib/drillClient.cpp
+++ b/contrib/native/client/src/clientlib/drillClient.cpp
@@ -181,6 +181,7 @@ const std::map<std::string, uint32_t>  DrillUserProperties::USER_PROPERTIES=boos
     ( USERPROP_USESSL,      USERPROP_FLAGS_BOOLEAN|USERPROP_FLAGS_SSLPROP)
     ( USERPROP_FILEPATH,    USERPROP_FLAGS_STRING|USERPROP_FLAGS_SSLPROP|USERPROP_FLAGS_FILEPATH)
     ( USERPROP_FILENAME,    USERPROP_FLAGS_STRING|USERPROP_FLAGS_SSLPROP|USERPROP_FLAGS_FILENAME)
+    ( USERPROP_SASL_ENCRYPT,  USERPROP_FLAGS_STRING)
 ;
 
 bool DrillUserProperties::validate(std::string& err){

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/drillClientImpl.cpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/drillClientImpl.cpp b/contrib/native/client/src/clientlib/drillClientImpl.cpp
index 30a354e..0dee309 100644
--- a/contrib/native/client/src/clientlib/drillClientImpl.cpp
+++ b/contrib/native/client/src/clientlib/drillClientImpl.cpp
@@ -30,7 +30,6 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/thread.hpp>
 
-
 #include "drill/drillClient.hpp"
 #include "drill/fieldmeta.hpp"
 #include "drill/recordBatch.hpp"
@@ -193,7 +192,7 @@ connectionStatus_t DrillClientImpl::sendHeartbeat(){
     boost::lock_guard<boost::mutex> prLock(this->m_prMutex);
     boost::lock_guard<boost::mutex> lock(m_dcMutex);
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Heartbeat sent." << std::endl;)
-    status=sendSync(heartbeatMsg);
+    status=sendSyncCommon(heartbeatMsg);
     status=status==CONN_SUCCESS?status:CONN_DEAD;
     //If the server sends responses to a heartbeat, we need to increment the pending requests counter.
     if(m_pendingRequests++==0){
@@ -233,18 +232,125 @@ void DrillClientImpl::Close() {
     shutdownSocket();
 }
 
+/*
+ * Write bytesToWrite length data bytes pointed by dataPtr. It handles EINTR error
+ * occurred during write_some sys call and does a retry on that.
+ *
+ * Parameters:
+ *      dataPtr      - in param   - Pointer to data bytes to write on socket.
+ *      bytesToWrite - in param   - Length of data bytes to write from dataPtr.
+ *      errorCode    -  out param - Error code set by boost.
+ */
+void DrillClientImpl::doWriteToSocket(const char* dataPtr, size_t bytesToWrite,
+                                        boost::system::error_code& errorCode) {
+    if(0 == bytesToWrite) {
+        return;
+    }
+
+    // Write all the bytes to socket. In case of error when all bytes are not successfully written
+    // proper errorCode will be set.
+    while(1) {
+        size_t bytesWritten = m_socket.write_some(boost::asio::buffer(dataPtr, bytesToWrite), errorCode);
+
+        // Update the state
+        bytesToWrite -= bytesWritten;
+        dataPtr += bytesWritten;
+
+        if(EINTR != errorCode.value()) break;
+
+        // Check if all the data is written then break from loop
+        if(0 == bytesToWrite) break;
+    }
+}
 
-connectionStatus_t DrillClientImpl::sendSync(rpc::OutBoundRpcMessage& msg){
+/*
+ * Common wrapper to take care of sending both plain or encrypted message. It creates a send buffer from an
+ * OutboundRPCMessage and then call the send handler pointing to either sendSyncPlain or sendSyncEncrypted
+ *
+ * Return:
+ *  connectionStatus_t  -   CONN_SUCCESS - In case of successful send
+ *                      -   CONN_FAILURE - In case of failure to send
+ */
+connectionStatus_t DrillClientImpl::sendSyncCommon(rpc::OutBoundRpcMessage& msg) {
     encode(m_wbuf, msg);
+    return (this->*m_fpCurrentSendHandler)();
+}
+
+/*
+ * Send handler for sending plain messages over wire
+ *
+ * Return:
+ *  connectionStatus_t  -   CONN_SUCCESS - In case of successful send
+ *                      -   CONN_FAILURE - In case of failure to send
+ */
+connectionStatus_t DrillClientImpl::sendSyncPlain(){
+
     boost::system::error_code ec;
-    size_t s=m_socket.write_some(boost::asio::buffer(m_wbuf), ec);
-    if(!ec && s!=0){
+    doWriteToSocket(reinterpret_cast<char*>(m_wbuf.data()), m_wbuf.size(), ec);
+
+    if(!ec) {
         return CONN_SUCCESS;
-    }else{
+    } else {
         return handleConnError(CONN_FAILURE, getMessage(ERR_CONN_WFAIL, ec.message().c_str()));
     }
 }
 
+/*
+ * Send handler for sending encrypted messages over wire. It encrypts the send buffer using wrap api provided by
+ * saslAuthenticatorImpl and then transmit the encrypted bytes over wire.
+ *
+ * Return:
+ *  connectionStatus_t  -   CONN_SUCCESS - In case of successful send
+ *                      -   CONN_FAILURE - In case of failure to send
+ */
+connectionStatus_t DrillClientImpl::sendSyncEncrypted() {
+
+    boost::system::error_code ec;
+
+    // Encoded message is encrypted into chunks of size <= WrapSizeLimit. Each encrypted chunk along with
+    // its encrypted length in network order (added by Cyrus-SASL plugin) is sent over wire.
+    const int wrapChunkSize = m_encryptionCtxt.getWrapSizeLimit();
+    int lengthToEncrypt = m_wbuf.size();
+
+    int currentChunkLen = std::min(wrapChunkSize, lengthToEncrypt);
+    uint32_t currentChunkOffset = 0;
+    std::stringstream errorMsg;
+
+    // Encrypt and send each chunk
+    while(lengthToEncrypt != 0) {
+        const char* wrappedChunk = NULL;
+        uint32_t wrappedLen = 0;
+        const int wrapResult = m_saslAuthenticator->wrap(reinterpret_cast<const char*>(m_wbuf.data() + currentChunkOffset),
+                                                   currentChunkLen, &wrappedChunk, wrappedLen);
+        if(SASL_OK != wrapResult) {
+            errorMsg << "Sasl wrap failed while encrypting chunk of length: " << currentChunkLen << " , EncodeError: "
+                     << wrapResult;
+            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::sendSyncEncrypted - " << errorMsg.str()
+                                              << " ,ChunkOffset: " << currentChunkOffset << ", Message Len: " << m_wbuf.size()
+                                              << ", Closing connection.";)
+            return handleConnError(CONN_FAILURE, getMessage(ERR_CONN_WFAIL, errorMsg.str().c_str()));
+        }
+
+        // Send the encrypted chunk.
+        doWriteToSocket(wrappedChunk, wrappedLen, ec);
+
+        if(ec) {
+            errorMsg << "Failure while sending encrypted chunk. Error: " << ec.message().c_str();
+            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::sendSyncEncrypted - " << errorMsg.str()
+                                              << ", Chunk Length: " << currentChunkLen << ", ChunkOffset:" << currentChunkOffset
+                                              << ", Message Len: " << m_wbuf.size() << ", Closing connection.";)
+            return handleConnError(CONN_FAILURE, getMessage(ERR_CONN_WFAIL, errorMsg.str().c_str()));
+        }
+
+        // Update variables after sending each encrypted chunk
+        lengthToEncrypt -= currentChunkLen;
+        currentChunkOffset += currentChunkLen;
+        currentChunkLen = std::min(wrapChunkSize, lengthToEncrypt);
+    }
+
+    return CONN_SUCCESS;
+}
+
 connectionStatus_t DrillClientImpl::recvHandshake(){
     if(m_rbuf==NULL){
         m_rbuf = Utils::allocateBuffer(MAX_SOCK_RD_BUFSIZE);
@@ -289,7 +395,41 @@ connectionStatus_t DrillClientImpl::recvHandshake(){
     return CONN_SUCCESS;
 }
 
-void DrillClientImpl::handleHandshake(ByteBuf_t _buf,
+/*
+ * Read bytesToRead length data bytes from socket into inBuf. It handles EINTR error
+ * occurred during read_some sys call and does a retry on that.
+ *
+ * Parameters:
+ *      inBuf        - out param  - Pointer to buffer to read data into from socket.
+ *      bytesToRead  - in param   - Length of data bytes to read from socket.
+ *      errorCode    - out param  - Error code set by boost.
+ */
+void DrillClientImpl::doReadFromSocket(ByteBuf_t inBuf, size_t bytesToRead,
+                                       boost::system::error_code& errorCode) {
+
+    // Check if bytesToRead is zero
+    if(0 == bytesToRead) {
+        return;
+    }
+
+    // Read all the bytes. In case when all the bytes were not read the proper
+    // errorCode will be set.
+    while(1){
+        size_t dataBytesRead = m_socket.read_some(boost::asio::buffer(inBuf, bytesToRead),
+                                           errorCode);
+        // Update the state
+        bytesToRead -= dataBytesRead;
+        inBuf += dataBytesRead;
+
+        // Check if errorCode is EINTR then just retry otherwise break from loop
+        if(EINTR != errorCode.value()) break;
+
+        // Check if all the data is read then break from loop
+        if(0 == bytesToRead) break;
+    }
+}
+
+void DrillClientImpl::handleHandshake(ByteBuf_t inBuf,
         const boost::system::error_code& err,
         size_t bytes_transferred) {
     boost::system::error_code error=err;
@@ -299,21 +439,23 @@ void DrillClientImpl::handleHandshake(ByteBuf_t _buf,
     if(!error){
         rpc::InBoundRpcMessage msg;
         uint32_t length = 0;
-        std::size_t bytes_read = rpc::lengthDecode(m_rbuf, length);
+        std::size_t bytes_read = rpcLengthDecode(m_rbuf, length);
         if(length>0){
-            size_t leftover = LEN_PREFIX_BUFLEN - bytes_read;
-            ByteBuf_t b=m_rbuf + LEN_PREFIX_BUFLEN;
-            size_t bytesToRead=length - leftover;
-            while(1){
-                size_t dataBytesRead=m_socket.read_some(
-                        boost::asio::buffer(b, bytesToRead),
-                        error);
-                if(err) break;
-                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Handshake Message: actual bytes read = " << dataBytesRead << std::endl;)
-                if(dataBytesRead==bytesToRead) break;
-                bytesToRead-=dataBytesRead;
-                b+=dataBytesRead;
+            const size_t leftover = LEN_PREFIX_BUFLEN - bytes_read;
+            const ByteBuf_t b = m_rbuf + LEN_PREFIX_BUFLEN;
+            const size_t bytesToRead=length - leftover;
+            doReadFromSocket(b, bytesToRead, error);
+
+            // Check if any error happen while reading the message bytes. If yes then return before decoding the Msg
+            if(error) {
+                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::handleHandshake: ERR_CONN_RDFAIL. "
+                                                  << " Failed to read entire handshake message. with error: "
+                                                  << error.message().c_str() << "\n";)
+                handleConnError(CONN_FAILURE, getMessage(ERR_CONN_RDFAIL, "Failed to read entire handshake message"));
+                return;
             }
+
+            // Decode the bytes into a valid RPC Message
             if (!decode(m_rbuf+bytes_read, length, msg)) {
                 DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::handleHandshake: ERR_CONN_RDFAIL. Cannot decode handshake.\n";)
                 handleConnError(CONN_FAILURE, getMessage(ERR_CONN_RDFAIL, "Cannot decode handshake"));
@@ -340,6 +482,11 @@ void DrillClientImpl::handleHandshake(ByteBuf_t _buf,
             this->m_serverAuthMechanisms.push_back(mechanism);
         }
 
+        // Updated encryption context based on server response
+        this->m_encryptionCtxt.setEncryptionReqd(b2u.has_encrypted() && b2u.encrypted());
+        if(b2u.has_maxwrappedsize()) {
+            this->m_encryptionCtxt.setMaxWrappedSize(b2u.maxwrappedsize());
+        }
     }else{
         // boost error
         if(error==boost::asio::error::eof){ // Server broke off the connection
@@ -360,7 +507,8 @@ void DrillClientImpl::handleHShakeReadTimeout(const boost::system::error_code &
         if (m_deadlineTimer.expires_at() <= boost::asio::deadline_timer::traits_type::now()){
             // The deadline has passed.
             m_deadlineTimer.expires_at(boost::posix_time::pos_infin);
-            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::HandleHShakeReadTimeout: Deadline timer expired; ERR_CONN_HSHAKETIMOUT.\n";)
+            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::HandleHShakeReadTimeout: "
+                                              << "Deadline timer expired; ERR_CONN_HSHAKETIMOUT.\n";)
             handleConnError(CONN_HANDSHAKE_TIMEOUT, getMessage(ERR_CONN_HSHAKETIMOUT));
             m_io_service.stop();
             boost::system::error_code ignorederr;
@@ -370,6 +518,33 @@ void DrillClientImpl::handleHShakeReadTimeout(const boost::system::error_code &
     return;
 }
 
+/*
+ * Check's if client has explicitly expressed interest in encrypted connections only. It looks for USERPROP_SASL_ENCRYPT
+ * connection string property. If set to true then returns true else returns false
+ */
+bool DrillClientImpl::clientNeedsEncryption(const DrillUserProperties* userProperties) {
+    bool needsEncryption = false;
+    // check if userProperties is null
+    if(!userProperties) {
+        return needsEncryption;
+    }
+
+    // Loop through the property to find USERPROP_SASL_ENCRYPT and it's value
+    for (size_t i = 0; i < userProperties->size(); i++) {
+        const std::string key = userProperties->keyAt(i);
+        std::string value = userProperties->valueAt(i);
+
+        if(USERPROP_SASL_ENCRYPT == key) {
+            boost::algorithm::to_lower(value);
+
+            if(0 == value.compare("true")) {
+                needsEncryption = true;
+            }
+        }
+    }
+    return needsEncryption;
+}
+
 connectionStatus_t DrillClientImpl::validateHandshake(DrillUserProperties* properties){
 
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "validateHandShake\n";)
@@ -379,7 +554,7 @@ connectionStatus_t DrillClientImpl::validateHandshake(DrillUserProperties* prope
     u2b.set_rpc_version(DRILL_RPC_VERSION);
     u2b.set_support_listening(true);
     u2b.set_support_timeout(DrillClientConfig::getHeartbeatFrequency() > 0);
-    u2b.set_sasl_support(exec::user::SASL_AUTH);
+    u2b.set_sasl_support(exec::user::SASL_PRIVACY);
 
     // Adding version info
     exec::user::RpcEndpointInfos* infos = u2b.mutable_client_infos();
@@ -436,7 +611,7 @@ connectionStatus_t DrillClientImpl::validateHandshake(DrillUserProperties* prope
         uint64_t coordId = this->getNextCoordinationId();
 
         rpc::OutBoundRpcMessage out_msg(exec::rpc::REQUEST, exec::user::HANDSHAKE, coordId, &u2b);
-        sendSync(out_msg);
+        sendSyncCommon(out_msg);
         DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Sent handshake request message. Coordination id: " << coordId << "\n";)
     }
 
@@ -479,6 +654,13 @@ connectionStatus_t DrillClientImpl::validateHandshake(DrillUserProperties* prope
 }
 
 connectionStatus_t DrillClientImpl::handleAuthentication(const DrillUserProperties *userProperties) {
+
+    // Check if client needs encryption and server is configured for encryption or not before starting handshake
+    if(clientNeedsEncryption(userProperties) && !m_encryptionCtxt.isEncryptionReqd()) {
+        return handleConnError(CONN_AUTH_FAILED, "Client needs encryption but on server side encryption is disabled."
+                                                 " Please check connection parameters or contact administrator?");
+    }
+
     try {
         m_saslAuthenticator = new SaslAuthenticatorImpl(userProperties);
     } catch (std::runtime_error& e) {
@@ -495,26 +677,46 @@ connectionStatus_t DrillClientImpl::handleAuthentication(const DrillUserProperti
         }
     }
 
+    std::stringstream logMsg;
+    logMsg << "DrillClientImpl::handleAuthentication: Authentication failed. [Details: ";
+
     if (SASL_OK == m_saslResultCode) {
-        DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "DrillClientImpl::handleAuthentication: Successfully authenticated!"
-                                          << std::endl;)
+        // Check the negotiated SSF value and change the handlers.
+        if(m_encryptionCtxt.isEncryptionReqd()) {
+            if(SASL_OK != m_saslAuthenticator->verifyAndUpdateSaslProps()) {
+                logMsg << m_encryptionCtxt << "]. Negotiated Parameter is invalid."
+                       << " Error: " << m_saslResultCode;
+                DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << logMsg.str() << std::endl;)
+                return handleConnError(CONN_AUTH_FAILED, logMsg.str().c_str());
+            }
+
+            // Successfully negotiated for encryption related security parameters.
+            // Start using Encrypt and Decrypt handlers.
+            m_fpCurrentSendHandler = &DrillClientImpl::sendSyncEncrypted;
+            m_fpCurrentReadMsgHandler = &DrillClientImpl::readAndDecryptMsg;
+        }
 
-        // in future, negotiated security layers are known here..
+        // Reset the errorMsg stream since this is success case.
+        logMsg.str(std::string());
+        logMsg << "DrillClientImpl::handleAuthentication: Successfully authenticated! [Details: "
+               << m_encryptionCtxt << " ]";
 
+        DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << logMsg.str() << std::endl;)
         m_io_service.reset();
         return CONN_SUCCESS;
     } else {
-        DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "DrillClientImpl::handleAuthentication: Authentication failed: "
-                                          << m_saslResultCode << std::endl;)
+        logMsg << m_encryptionCtxt << ", Error: " << m_saslResultCode;
+        DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << logMsg.str() << std::endl;)
+
         // shuts down socket as well
-        return handleConnError(CONN_AUTH_FAILED, "Authentication failed. Check connection parameters?");
+        logMsg << "]. Check connection parameters?";
+        return handleConnError(CONN_AUTH_FAILED, logMsg.str().c_str());
     }
 }
 
 void DrillClientImpl::initiateAuthentication() {
     exec::shared::SaslMessage response;
-    m_saslResultCode = m_saslAuthenticator->init(m_serverAuthMechanisms, response);
-
+    m_saslResultCode = m_saslAuthenticator->init(m_serverAuthMechanisms, response, &m_encryptionCtxt);
 
     switch (m_saslResultCode) {
         case SASL_CONTINUE:
@@ -539,7 +741,7 @@ void DrillClientImpl::sendSaslResponse(const exec::shared::SaslMessage& response
     boost::lock_guard<boost::mutex> lock(m_dcMutex);
     const int32_t coordId = getNextCoordinationId();
     rpc::OutBoundRpcMessage msg(exec::rpc::REQUEST, exec::user::SASL_MESSAGE, coordId, &response);
-    sendSync(msg);
+    sendSyncCommon(msg);
     if (m_pendingRequests++ == 0) {
         getNextResult();
     }
@@ -768,23 +970,23 @@ Handle* DrillClientImpl::sendMsg(boost::function<Handle*(int32_t)> handleFactory
         phandle = handleFactory(coordId);
         this->m_queryHandles[coordId]=phandle;
 
-        connectionStatus_t cStatus=sendSync(out_msg);
+        connectionStatus_t cStatus = sendSyncCommon(out_msg);
         if(cStatus == CONN_SUCCESS){
             bool sendRequest=false;
 
             DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG)  << "Sent " << ::exec::user::RpcType_Name(type) << " request. " << "[" << m_connectedHost << "]"  << "Coordination id = " << coordId << std::endl;)
-                DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG)  << "Sent " << ::exec::user::RpcType_Name(type) <<  " Coordination id = " << coordId << " query: " << phandle->getQuery() << std::endl;)
+            DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG)  << "Sent " << ::exec::user::RpcType_Name(type) <<  " Coordination id = " << coordId << " query: " << phandle->getQuery() << std::endl;)
 
-                if(m_pendingRequests++==0){
-                    sendRequest=true;
-                }else{
-                    DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "Queuing " << ::exec::user::RpcType_Name(type) <<  " request to server" << std::endl;)
-                        DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "Number of pending requests = " << m_pendingRequests << std::endl;)
-                }
+            if(m_pendingRequests++==0){
+                sendRequest=true;
+            }else{
+                DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "Queuing " << ::exec::user::RpcType_Name(type) <<  " request to server" << std::endl;)
+                DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "Number of pending requests = " << m_pendingRequests << std::endl;)
+            }
             if(sendRequest){
                 DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "Sending " << ::exec::user::RpcType_Name(type) <<  " request. Number of pending requests = "
                         << m_pendingRequests << std::endl;)
-                    getNextResult(); // async wait for results
+                getNextResult(); // async wait for results
             }
         }
 
@@ -854,76 +1056,319 @@ void DrillClientImpl::waitForResults(){
     }
 }
 
-status_t DrillClientImpl::readMsg(ByteBuf_t _buf,
-        AllocatedBufferPtr* allocatedBuffer,
-        rpc::InBoundRpcMessage& msg){
+/*
+ *  Decode the length of the message from bufWithLen and then read entire message from the socket.
+ *  Parameters:
+ *      bufWithLenField            - in  param  - buffer containing the length of the RPC message/encrypted chunk
+ *      bufferWithDataAndLenBytes  - out param  - buffer pointer which points to memory allocated in this function and has the
+ *                                                entire one RPC message / encrypted chunk along with the length of the message.
+ *                                                Memory for this buffer is released by caller.
+ *      lengthFieldLength          - out param  - bytes of bufWithLen which contains the length of the entire RPC message or
+ *                                                encrypted chunk
+ *      lengthDecodeHandler        - in  param  - function pointer with length decoder to use. For encrypted chunk we use
+ *                                                lengthDecode and for plain RPC message we use rpcLengthDecode.
+ *  Return:
+ *      status_t    - QRY_SUCCESS    - In case of success.
+ *                  - QRY_COMM_ERROR/QRY_INTERNAL_ERROR/QRY_CLIENT_OUTOFMEM - In cases of error.
+ */
+status_t DrillClientImpl::readLenBytesFromSocket(const ByteBuf_t bufWithLenField, AllocatedBufferPtr* bufferWithDataAndLenBytes,
+                                                 uint32_t& lengthFieldLength, lengthDecoder lengthDecodeHandler) {
+
+    uint32_t rmsgLen = 0;
+    boost::system::error_code error;
+    *bufferWithDataAndLenBytes = NULL;
+
+    // Decode the length field
+    lengthFieldLength = (this->*lengthDecodeHandler)(bufWithLenField, rmsgLen);
+
+    DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Length bytes = " << lengthFieldLength << std::endl;)
+    DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Msg Length = " << rmsgLen << std::endl;)
+
+    if(rmsgLen>0) {
+        const size_t leftover = LEN_PREFIX_BUFLEN - lengthFieldLength;
+
+        // Allocate a buffer for reading all the bytes in bufWithLen and length number of bytes.
+        const size_t bufferSizeWithLenBytes = rmsgLen + lengthFieldLength;
+        *bufferWithDataAndLenBytes = new AllocatedBuffer(bufferSizeWithLenBytes);
+
+        if(*bufferWithDataAndLenBytes == NULL) {
+            return handleQryError(QRY_CLIENT_OUTOFMEM, getMessage(ERR_QRY_OUTOFMEM), NULL);
+        }
+
+        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readLenBytesFromSocket: Allocated and locked buffer: [ "
+                                          << *bufferWithDataAndLenBytes << ", size = " << bufferSizeWithLenBytes << " ]\n";)
+
+        // Copy the memory of bufWithLen into bufferWithLenBytesSize
+        memcpy((*bufferWithDataAndLenBytes)->m_pBuffer, bufWithLenField, LEN_PREFIX_BUFLEN);
+        const size_t bytesToRead = rmsgLen - leftover;
+        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Copied bufWithLen into bufferWithLenBytes. "
+                                          << "Now reading data (rmsgLen - leftover) : " << bytesToRead
+                                          << std::endl;)
+
+        // Read the entire data left from socket and copy to currentBuffer.
+        const ByteBuf_t b = (*bufferWithDataAndLenBytes)->m_pBuffer + LEN_PREFIX_BUFLEN;
+        doReadFromSocket(b, bytesToRead, error);
+    } else {
+        return handleQryError(QRY_INTERNAL_ERROR, getMessage(ERR_QRY_INVREADLEN), NULL);
+    }
+
+    return error ? handleQryError(QRY_COMM_ERROR, getMessage(ERR_QRY_COMMERR, error.message().c_str()), NULL)
+                 : QRY_SUCCESS;
+}
+
+
+/*
+ *  Function to read entire RPC message from socket and decode it to InboundRpcMessage
+ *  Parameters:
+ *      inBuf           - in param  - Buffer containing the length bytes.
+ *      allocatedBuffer - out param - Buffer containing the length bytes and entire RPC message bytes.
+ *      msg             - out param - Decoded InBoundRpcMessage from the bytes in allocatedBuffer
+ *  Return:
+ *      status_t    - QRY_SUCCESS   - In case of success.
+ *                  - QRY_COMM_ERROR/QRY_INTERNAL_ERROR/QRY_CLIENT_OUTOFMEM - In cases of error.
+ */
+status_t DrillClientImpl::readMsg(const ByteBuf_t inBuf, AllocatedBufferPtr* allocatedBuffer,
+                                  rpc::InBoundRpcMessage& msg){
 
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readMsg: Read message from buffer "
-        <<  reinterpret_cast<int*>(_buf) << std::endl;)
-    size_t leftover=0;
-    uint32_t rmsgLen;
-    AllocatedBufferPtr currentBuffer;
-    *allocatedBuffer=NULL;
+                                      <<  reinterpret_cast<int*>(inBuf) << std::endl;)
+    *allocatedBuffer = NULL;
+    {
+        // We need to protect the readLength and read buffer, and the pending requests counter,
+        // but we don't have to keep the lock while we decode the rest of the buffer.
+        boost::lock_guard<boost::mutex> lock(this->m_dcMutex);
+        uint32_t lengthFieldSize = 0;
+
+        // Read the message length and extract length size bytes to form InBoundRpcMessage
+        const status_t statusCode = readLenBytesFromSocket(inBuf, allocatedBuffer, lengthFieldSize,
+                                                           &DrillClientImpl::rpcLengthDecode);
+
+        // Check for error conditions
+        if(QRY_SUCCESS != statusCode) {
+            Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+            return statusCode;
+        }
+
+        // Get the message size
+        size_t msgLen = (*allocatedBuffer)->m_bufSize;
+
+        // Read data successfully, now let's try to decode the buffer and form a valid RPC message.
+        // allocatedBuffer also contains the length bytes which is not needed by decodes so skip that part of buffer.
+        // We have it since in case of encryption the unwrap function expects it
+        if (!decode((*allocatedBuffer)->m_pBuffer + lengthFieldSize, msgLen - lengthFieldSize, msg)) {
+            Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+            return handleQryError(QRY_COMM_ERROR, getMessage(ERR_QRY_COMMERR, "Cannot decode server message"), NULL);
+        }
+
+        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Successfully created a RPC message with Coordination id: "
+                                          << msg.m_coord_id << std::endl;)
+    }
+    DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readMsg: Free buffer "
+                                      <<  reinterpret_cast<int*>(inBuf) << std::endl;)
+    Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+    return QRY_SUCCESS;
+}
+
+
+/*
+ *  Read ENCRYPT_LEN_PREFIX_BUFLEN bytes to decode length of one complete encrypted chunk. The length bytes are expected
+ *  to be in network order. It is converted to host order and the value is stored in rmsgLen parameter.
+ *  Parameters:
+ *      inBuf   - in param  - ByteBuf_t containing atleast the length bytes.
+ *      rmsgLen - out param - Contain the decoded value of length.
+ *  Return:
+ *      size_t  - length bytes read to decode
+ */
+size_t DrillClientImpl::lengthDecode(const ByteBuf_t inBuf, uint32_t& rmsgLen) {
+    memcpy(&rmsgLen, inBuf, ENCRYPT_LEN_PREFIX_BUFLEN);
+    rmsgLen = ntohl(rmsgLen);
+    return ENCRYPT_LEN_PREFIX_BUFLEN;
+}
+
+/*
+ *  Wrapper which uses RPC message length decoder to get length of one complete RPC message from _buf.
+ *  Parameters:
+ *      inBuf   - in param  - ByteBuf_t containing atleast the length bytes.
+ *      rmsgLen - out param - Contain the decoded value of length.
+ *  Return:
+ *      size_t	- length bytes read to decode
+ */
+size_t DrillClientImpl::rpcLengthDecode(const ByteBuf_t inBuf, uint32_t& rmsgLen) {
+    return rpc::lengthDecode(inBuf, rmsgLen);
+}
+
+
+/*
+ *  Read all the encrypted chunk needed to form a complete RPC message. Read an entire chunk from network, decrypt it
+ *  and put in a buffer. The same process is repeated until the entire buffer to form a completed RPC message is read.
+ *  Parameters:
+ *      inBuf           - in param  - ByteBuf_t containing atleast the length bytes.
+ *      allocatedBuffer - out param - Buffer containing the entire RPC message bytes which is formed by reading all the
+ *                                    required encrypted chunk from network and decrypting each individual chunk. The
+ *                                    buffer memory is released by caller.
+.*      msg             - out param - InBoundRpcMessage formed from bytes in allocatedBuffer
+ *  Return:
+ *      status_t    - QRY_SUCCESS - In case of success.
+ *                  - QRY_COMM_ERROR/QRY_INTERNAL_ERROR/QRY_CLIENT_OUTOFMEM - In cases of error.
+ */
+status_t DrillClientImpl::readAndDecryptMsg(const ByteBuf_t inBuf, AllocatedBufferPtr* allocatedBuffer,
+                                            rpc::InBoundRpcMessage& msg) {
+
+    DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Read message from buffer "
+                                      << reinterpret_cast<int*>(inBuf) << std::endl;)
+
+    size_t leftover = 0;
+    uint32_t rpcMsgLen = 0;
+    size_t bytes_read = 0;
+    uint32_t writeIndex = 0;
+    size_t bytesToRead = 0;
+
+    *allocatedBuffer = NULL;
+    boost::system::error_code error;
+    std::stringstream errorMsg;
+
     {
         // We need to protect the readLength and read buffer, and the pending requests counter,
         // but we don't have to keep the lock while we decode the rest of the buffer.
         boost::lock_guard<boost::mutex> lock(this->m_dcMutex);
-        std::size_t bytes_read = rpc::lengthDecode(_buf, rmsgLen);
-        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "len bytes = " << bytes_read << std::endl;)
-        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "rmsgLen = " << rmsgLen << std::endl;)
-
-        if(rmsgLen>0){
-            leftover = LEN_PREFIX_BUFLEN - bytes_read;
-            // Allocate a buffer
-            currentBuffer=new AllocatedBuffer(rmsgLen);
-            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readMsg: Allocated and locked buffer: [ "
-                << currentBuffer << ", size = " << rmsgLen << " ]\n";)
-            if(currentBuffer==NULL){
-                Utils::freeBuffer(_buf, LEN_PREFIX_BUFLEN);
-                return handleQryError(QRY_CLIENT_OUTOFMEM, getMessage(ERR_QRY_OUTOFMEM), NULL);
+
+        do{
+            AllocatedBufferPtr currentBuffer = NULL;
+            uint32_t lengthFieldSize = 0;
+            const status_t statusCode = readLenBytesFromSocket(inBuf, &currentBuffer, lengthFieldSize,
+                                                               &DrillClientImpl::lengthDecode);
+
+            if(QRY_SUCCESS != statusCode) {
+                Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+
+                // Release the buffer allocated to hold chunk
+                if(currentBuffer != NULL) {
+                    Utils::freeBuffer(currentBuffer->m_pBuffer, currentBuffer->m_bufSize);
+                    currentBuffer = NULL;
+                }
+                return statusCode;
             }
-            *allocatedBuffer=currentBuffer;
-            if(leftover){
-                memcpy(currentBuffer->m_pBuffer, _buf + bytes_read, leftover);
+
+            // read one chunk successfully. Let's try to decrypt the message
+            const char* unWrappedData = NULL;
+            uint32_t unWrappedLen = 0;
+            const int decryptResult = m_saslAuthenticator->unwrap(reinterpret_cast<const char*>(currentBuffer->m_pBuffer),
+                                                                  currentBuffer->m_bufSize, &unWrappedData, unWrappedLen);
+
+            if(SASL_OK != decryptResult) {
+
+                errorMsg << "Sasl unwrap failed for the buffer of size:" << currentBuffer->m_bufSize << " , Error: "
+                         << decryptResult;
+
+                DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "DrillClientImpl::readAndDecryptMsg: "
+                                                  << errorMsg.str() << std::endl;)
+
+                Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+
+                // Release the buffer allocated to hold chunk
+                Utils::freeBuffer(currentBuffer->m_pBuffer, currentBuffer->m_bufSize);
+                currentBuffer = NULL;
+                return handleQryError(QRY_COMM_ERROR,
+                                      getMessage(ERR_QRY_COMMERR, errorMsg.str().c_str()), NULL);
             }
-            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "reading data (rmsgLen - leftover) : "
-                << (rmsgLen - leftover) << std::endl;)
-            ByteBuf_t b=currentBuffer->m_pBuffer + leftover;
-            size_t bytesToRead=rmsgLen - leftover;
-            boost::system::error_code error;
-            while(1){
-                size_t dataBytesRead=this->m_socket.read_some(
-                        boost::asio::buffer(b, bytesToRead),
-                        error);
-                if(error) break;
-                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Data Message: actual bytes read = " << dataBytesRead << std::endl;)
-                if(dataBytesRead==bytesToRead) break;
-                bytesToRead-=dataBytesRead;
-                b+=dataBytesRead;
+
+            // Check for case if the unWrappedLen is 0, since Cyrus SASL plugin verifies if the length of wrapped data
+            // is less than the length specified by prepended 4 octets as per RFC 4422/2222. If so it just returns
+            // and waits for more data
+            if(unWrappedLen == 0 || (unWrappedData == NULL)) {
+                errorMsg << "Sasl unwrap failed with mismatch in length of wrapped data and the prepended length value";
+                DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "DrillClientImpl::readAndDecryptMsg: " << errorMsg.str()
+                                                  << std::endl;)
+
+                Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+
+                // Release the buffer allocated to hold chunk
+                Utils::freeBuffer(currentBuffer->m_pBuffer, currentBuffer->m_bufSize);
+                currentBuffer = NULL;
+                return handleQryError(QRY_COMM_ERROR,
+                                      getMessage(ERR_QRY_COMMERR, errorMsg.str().c_str()), NULL);
             }
 
-            if(!error){
-                // read data successfully
-                if (!decode(currentBuffer->m_pBuffer, rmsgLen, msg)) {
-                    Utils::freeBuffer(_buf, LEN_PREFIX_BUFLEN);
-                    return handleQryError(QRY_COMM_ERROR,
-                            getMessage(ERR_QRY_COMMERR, "Cannot decode server message"), NULL);;
+            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Successfully decrypted the buffer"
+                                              << " Sizes - Before Decryption =  " << currentBuffer->m_bufSize
+                                              << " and After Decryption = " << unWrappedLen << std::endl;)
+
+            // Release the buffer allocated to hold chunk
+            Utils::freeBuffer(currentBuffer->m_pBuffer, currentBuffer->m_bufSize);
+            currentBuffer = NULL;
+
+            bytes_read = 0;
+            if(*allocatedBuffer == NULL) {
+                // This is the first chunk of the RPC message. We will decode the RPC message full length
+                bytes_read = rpcLengthDecode(reinterpret_cast<ByteBuf_t>(const_cast<char*>(unWrappedData)), rpcMsgLen);
+
+                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Rpc Message Length bytes = "
+                                                  << bytes_read << std::endl;)
+                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Rpc Message Length = "
+                                                  << rpcMsgLen << std::endl;)
+
+                if(rpcMsgLen == 0) {
+                    Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+                    return handleQryError(QRY_INTERNAL_ERROR, getMessage(ERR_QRY_INVREADLEN), NULL);
                 }
-                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Done decoding chunk. Coordination id: " <<msg.m_coord_id<< std::endl;)
-            }else{
-                Utils::freeBuffer(_buf, LEN_PREFIX_BUFLEN);
-                return handleQryError(QRY_COMM_ERROR,
-                        getMessage(ERR_QRY_COMMERR, error.message().c_str()), NULL);
+                // Allocate a buffer for storing full RPC message. This is released by the caller
+                *allocatedBuffer = new AllocatedBuffer(rpcMsgLen);
+
+                if(*allocatedBuffer == NULL){
+                    Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+                    return handleQryError(QRY_CLIENT_OUTOFMEM, getMessage(ERR_QRY_OUTOFMEM), NULL);
+                }
+
+                DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg:  Allocated and locked buffer:"
+                                                  << "[ " << *allocatedBuffer << ", size = " << rpcMsgLen << " ]\n";)
+
+                bytesToRead = rpcMsgLen;
             }
-        }else{
-            // got a message with an invalid read length.
-            Utils::freeBuffer(_buf, LEN_PREFIX_BUFLEN);
-            return handleQryError(QRY_INTERNAL_ERROR, getMessage(ERR_QRY_INVREADLEN), NULL);
+
+            // Update the leftover bytes that is not copied yet
+            leftover = unWrappedLen - bytes_read;
+
+            // Copy rest of decrypted message to the buffer. We can do this since it is assured that one
+            // entire decrypted chunk is part of the same RPC message.
+            if(leftover) {
+                memcpy((*allocatedBuffer)->m_pBuffer + writeIndex, unWrappedData + bytes_read, leftover);
+            }
+
+            // Update bytes left to read to form full RPC message.
+            bytesToRead -= leftover;
+            writeIndex += leftover;
+
+            DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Left to read unencrypted data"
+                                              << " of length (bytesToRead) : " << bytesToRead << std::endl;)
+
+            if(bytesToRead > 0) {
+                // Read synchronously buffer of size LEN_PREFIX_BUFLEN to get length of next chunk
+                doReadFromSocket(inBuf, LEN_PREFIX_BUFLEN, error);
+
+                if(error) {
+                    Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+                    return handleQryError(QRY_COMM_ERROR, getMessage(ERR_QRY_COMMERR, error.message().c_str()), NULL);
+                }
+            }
+        }while(bytesToRead > 0); // more chunks to read for entire RPC message
+
+        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Done decrypting entire RPC message "
+                                          << " of length: " << rpcMsgLen << ". Now starting decode:" << std::endl;)
+
+        // Decode the buffer and form a RPC message
+        if (!decode((*allocatedBuffer)->m_pBuffer, rpcMsgLen, msg)) {
+            Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
+            return handleQryError(QRY_COMM_ERROR, getMessage(ERR_QRY_COMMERR,
+                                  "Cannot decode server message into valid RPC message"), NULL);
         }
+
+        DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Successfully created a RPC message with Coordination id: "
+                                          << msg.m_coord_id << std::endl;)
     }
-    DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readMsg: Free buffer "
-        <<  reinterpret_cast<int*>(_buf) << std::endl;)
-    Utils::freeBuffer(_buf, LEN_PREFIX_BUFLEN);
+
+    DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::readAndDecryptMsg: Free buffer "
+                                      <<  reinterpret_cast<int*>(inBuf) << std::endl;)
+    Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
     return QRY_SUCCESS;
 }
 
@@ -1364,15 +1809,15 @@ status_t DrillClientImpl::processServerMetaResult(AllocatedBufferPtr allocatedBu
     std::map<int,DrillClientQueryHandle*>::const_iterator it=this->m_queryHandles.find(msg.m_coord_id);
     if(it!=this->m_queryHandles.end()){
         DrillClientServerMetaHandle* pHandle=static_cast<DrillClientServerMetaHandle*>((*it).second);
+        exec::user::GetServerMetaResp* resp = new exec::user::GetServerMetaResp();
         DRILL_MT_LOG(DRILL_LOG(LOG_TRACE)  << "Received GetServerMetaResp result Handle " << msg.m_pbody.size() << std::endl;)
-        exec::user::GetServerMetaResp resp;
-        if (!(resp.ParseFromArray(msg.m_pbody.data(), msg.m_pbody.size()))) {
+        if (!(resp->ParseFromArray(msg.m_pbody.data(), msg.m_pbody.size()))) {
             return handleQryError(QRY_COMM_ERROR, "Cannot decode GetServerMetaResp results", pHandle);
         }
-        if (resp.status() != exec::user::OK) {
-            return handleQryError(QRY_FAILED, resp.error(), pHandle);
+        if (resp->status() != exec::user::OK) {
+            return handleQryError(QRY_FAILED, resp->error(), pHandle);
         }
-        pHandle->notifyListener(&(resp.server_meta()), NULL);
+        pHandle->notifyListener(&(resp->server_meta()), NULL);
         DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "GetServerMetaResp result " << std::endl;)
     }else{
         return handleQryError(QRY_INTERNAL_ERROR, getMessage(ERR_QRY_INVQUERYID), NULL);
@@ -1484,11 +1929,11 @@ void DrillClientImpl::handleReadTimeout(const boost::system::error_code & err){
     return;
 }
 
-void DrillClientImpl::handleRead(ByteBuf_t _buf,
+void DrillClientImpl::handleRead(ByteBuf_t inBuf,
         const boost::system::error_code& error,
         size_t bytes_transferred) {
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::handleRead: Handle Read from buffer "
-        <<  reinterpret_cast<int*>(_buf) << std::endl;)
+        <<  reinterpret_cast<int*>(inBuf) << std::endl;)
     if(DrillClientConfig::getQueryTimeout() > 0){
         // Cancel the timeout if handleRead is called
         DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::handleRead: Cancel deadline timer.\n";)
@@ -1496,7 +1941,7 @@ void DrillClientImpl::handleRead(ByteBuf_t _buf,
     }
     if (error) {
         // boost error
-        Utils::freeBuffer(_buf, LEN_PREFIX_BUFLEN);
+        Utils::freeBuffer(inBuf, LEN_PREFIX_BUFLEN);
         boost::lock_guard<boost::mutex> lock(this->m_dcMutex);
         DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "DrillClientImpl::handleRead: ERR_QRY_COMMERR. "
             "Boost Communication Error: " << error.message() << std::endl;)
@@ -1510,7 +1955,7 @@ void DrillClientImpl::handleRead(ByteBuf_t _buf,
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Getting new message" << std::endl;)
     AllocatedBufferPtr allocatedBuffer=NULL;
 
-    if(readMsg(_buf, &allocatedBuffer, msg)!=QRY_SUCCESS){
+    if((this->*m_fpCurrentReadMsgHandler)(inBuf, &allocatedBuffer, msg)!=QRY_SUCCESS){
         delete allocatedBuffer;
         if(m_pendingRequests!=0){
             boost::lock_guard<boost::mutex> lock(this->m_dcMutex);
@@ -1655,6 +2100,9 @@ status_t DrillClientImpl::validateResultMessage(const rpc::InBoundRpcMessage& ms
     return QRY_SUCCESS;
 }
 
+/*
+ * Called when there is failure in connect/send.
+ */
 connectionStatus_t DrillClientImpl::handleConnError(connectionStatus_t status, const std::string& msg){
     DrillClientError* pErr = new DrillClientError(status, DrillClientError::CONN_ERROR_START+status, msg);
     m_pendingRequests=0;
@@ -1669,19 +2117,28 @@ connectionStatus_t DrillClientImpl::handleConnError(connectionStatus_t status, c
     return status;
 }
 
+/*
+ * Always called with NULL QueryHandle when there is any error while reading data from socket. Once enough data is read
+ * and a valid RPC message is formed then it can get called with NULL/valid QueryHandle depending on if QueryHandle is found
+ * for the created RPC message.
+ */
 status_t DrillClientImpl::handleQryError(status_t status, const std::string& msg, DrillClientQueryHandle* pQueryHandle){
     DrillClientError* pErr = new DrillClientError(status, DrillClientError::QRY_ERROR_START+status, msg);
-    // set query error only if queries are running
+    // Set query error only if queries are running. If valid QueryHandle that means the bytes to form a valid
+    // RPC message was read successfully from socket. So there is no socket/connection issues.
     if(pQueryHandle!=NULL){
         m_pendingRequests--;
         pQueryHandle->signalError(pErr);
-    }else{
+    }else{ // This means error was while reading from socket, hence call broadcastError which eventually closes socket.
         m_pendingRequests=0;
         broadcastError(pErr);
     }
     return status;
 }
 
+/*
+ * Always called with valid QueryHandle when there is any error processing Query related data.
+ */
 status_t DrillClientImpl::handleQryError(status_t status,
         const exec::shared::DrillPBError& e,
         DrillClientQueryHandle* pQueryHandle){
@@ -1766,7 +2223,7 @@ void DrillClientImpl::sendAck(const rpc::InBoundRpcMessage& msg, bool isOk){
     ack.set_ok(isOk);
     rpc::OutBoundRpcMessage ack_msg(exec::rpc::RESPONSE, exec::user::ACK, msg.m_coord_id, &ack);
     boost::lock_guard<boost::mutex> lock(m_dcMutex);
-    sendSync(ack_msg);
+    sendSyncCommon(ack_msg);
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "ACK sent" << std::endl;)
 }
 
@@ -1774,7 +2231,7 @@ void DrillClientImpl::sendCancel(const exec::shared::QueryId* pQueryId){
     boost::lock_guard<boost::mutex> lock(m_dcMutex);
     uint64_t coordId = this->getNextCoordinationId();
     rpc::OutBoundRpcMessage cancel_msg(exec::rpc::REQUEST, exec::user::CANCEL_QUERY, coordId, pQueryId);
-    sendSync(cancel_msg);
+    sendSyncCommon(cancel_msg);
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "CANCEL sent" << std::endl;)
 }
 
@@ -1783,6 +2240,21 @@ void DrillClientImpl::shutdownSocket(){
     boost::system::error_code ignorederr;
     m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignorederr);
     m_bIsConnected=false;
+
+    // Delete the saslAuthenticatorImpl instance since connection is broken. It will recreated on next
+    // call to connect.
+    if(m_saslAuthenticator != NULL) {
+        delete m_saslAuthenticator;
+        m_saslAuthenticator = NULL;
+    }
+
+    // Reset the SASL states.
+    m_saslDone = false;
+    m_saslResultCode = SASL_OK;
+
+    // Reset the encryption context since connection is invalid
+    m_encryptionCtxt.reset();
+
     DRILL_MT_LOG(DRILL_LOG(LOG_TRACE) << "Socket shutdown" << std::endl;)
 }
 
@@ -1799,8 +2271,6 @@ struct ServerMetaContext {
 	boost::mutex m_mutex;
 	boost::condition_variable m_cv;
 
-    ServerMetaContext(): m_done(false), m_status(QRY_SUCCESS), m_serverMeta(), m_mutex(), m_cv() {};
-
 	static status_t listener(void* ctx, const exec::user::ServerMeta* serverMeta, DrillClientError* err) {
 		ServerMetaContext* context = static_cast<ServerMetaContext*>(ctx);
 			if (err) {

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/drillClientImpl.hpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/drillClientImpl.hpp b/contrib/native/client/src/clientlib/drillClientImpl.hpp
index d37076e..852233f 100644
--- a/contrib/native/client/src/clientlib/drillClientImpl.hpp
+++ b/contrib/native/client/src/clientlib/drillClientImpl.hpp
@@ -368,16 +368,17 @@ class DrillClientColumnResult: public DrillClientMetadataResult<Metadata::pfnCol
     	DrillClientMetadataResult<Metadata::pfnColumnMetadataListener, meta::ColumnMetadata, meta::DrillColumnMetadata, exec::user::GetColumnsResp>(client, coordId, "getColumns", listener, listenerCtx) {}
 };
 
+// Length Decoder Function Pointer definition
+typedef size_t (DrillClientImpl::*lengthDecoder)(const ByteBuf_t, uint32_t&);
 
 class DrillClientImpl : public DrillClientImplBase{
     public:
         DrillClientImpl():
-            m_coordinationId(1),
             m_handshakeVersion(0),
             m_handshakeStatus(exec::user::SUCCESS),
             m_bIsConnected(false),
             m_saslAuthenticator(NULL),
-    		m_saslResultCode(SASL_OK),
+            m_saslResultCode(SASL_OK),
             m_saslDone(false),
             m_pendingRequests(0),
             m_pError(NULL),
@@ -388,9 +389,11 @@ class DrillClientImpl : public DrillClientImplBase{
             m_heartbeatTimer(m_io_service),
             m_rbuf(NULL),
             m_wbuf(MAX_SOCK_RD_BUFSIZE),
-			m_bIsDirectConnection(false)
+            m_bIsDirectConnection(false)
     {
         m_coordinationId=rand()%1729+1;
+        m_fpCurrentReadMsgHandler = &DrillClientImpl::readMsg;
+        m_fpCurrentSendHandler = &DrillClientImpl::sendSyncPlain;
     };
 
         ~DrillClientImpl(){
@@ -477,9 +480,10 @@ class DrillClientImpl : public DrillClientImplBase{
         void handleHeartbeatTimeout(const boost::system::error_code & err); // send a heartbeat. If send fails, broadcast error, close connection and bail out.
 
         int32_t getNextCoordinationId(){ return ++m_coordinationId; };
-        // send synchronous messages
-        //connectionStatus_t recvSync(rpc::InBoundRpcMessage& msg);
-        connectionStatus_t sendSync(rpc::OutBoundRpcMessage& msg);
+        // synchronous message send handlers
+        connectionStatus_t sendSyncCommon(rpc::OutBoundRpcMessage& msg);
+        connectionStatus_t sendSyncPlain();
+        connectionStatus_t sendSyncEncrypted();
         // handshake
         connectionStatus_t recvHandshake();
         void handleHandshake(ByteBuf_t b, const boost::system::error_code& err, std::size_t bytes_transferred );
@@ -488,10 +492,16 @@ class DrillClientImpl : public DrillClientImplBase{
         void startMessageListener(); 
         // Query results
         void getNextResult();
-        status_t readMsg(
-                ByteBuf_t _buf,
-                AllocatedBufferPtr* allocatedBuffer,
-                rpc::InBoundRpcMessage& msg);
+        // Read Message Handlers
+        status_t readMsg(const ByteBuf_t inBuf, AllocatedBufferPtr* allocatedBuffer, rpc::InBoundRpcMessage& msg);
+        status_t readAndDecryptMsg(const ByteBuf_t inBuf, AllocatedBufferPtr* allocatedBuffer, rpc::InBoundRpcMessage& msg);
+        status_t readLenBytesFromSocket(const ByteBuf_t bufWithLenField, AllocatedBufferPtr* bufferWithDataAndLenBytes,
+                                        uint32_t& lengthFieldLength, lengthDecoder lengthDecodeHandler);
+        void doReadFromSocket(ByteBuf_t inBuf, size_t bytesToRead, boost::system::error_code& errorCode);
+        void doWriteToSocket(const char* dataPtr, size_t bytesToWrite, boost::system::error_code& errorCode);
+        // Length decode handlers
+        size_t lengthDecode(const ByteBuf_t inBuf, uint32_t& rmsgLen);
+        size_t rpcLengthDecode(const ByteBuf_t inBuf, uint32_t& rmsgLen);
         status_t processQueryResult(AllocatedBufferPtr allocatedBuffer, const rpc::InBoundRpcMessage& msg);
         status_t processQueryData(AllocatedBufferPtr allocatedBuffer, const rpc::InBoundRpcMessage& msg);
         status_t processCancelledQueryResult( exec::shared::QueryId& qid, exec::shared::QueryResult* qr);
@@ -506,7 +516,7 @@ class DrillClientImpl : public DrillClientImplBase{
         status_t processQueryStatusResult( exec::shared::QueryResult* qr,
                 DrillClientQueryResult* pDrillClientQueryResult);
         void handleReadTimeout(const boost::system::error_code & err);
-        void handleRead(ByteBuf_t _buf, const boost::system::error_code & err, size_t bytes_transferred) ;
+        void handleRead(ByteBuf_t inBuf, const boost::system::error_code & err, size_t bytes_transferred) ;
         status_t validateDataMessage(const rpc::InBoundRpcMessage& msg, const exec::shared::QueryData& qd, std::string& valError);
         status_t validateResultMessage(const rpc::InBoundRpcMessage& msg, const exec::shared::QueryResult& qr, std::string& valError);
         connectionStatus_t handleConnError(connectionStatus_t status, const std::string& msg);
@@ -540,6 +550,7 @@ class DrillClientImpl : public DrillClientImplBase{
         void finishAuthentication();
 
         void shutdownSocket();
+        bool clientNeedsEncryption(const DrillUserProperties* userProperties);
 
         int32_t m_coordinationId;
         int32_t m_handshakeVersion;
@@ -557,6 +568,14 @@ class DrillClientImpl : public DrillClientImplBase{
         boost::mutex m_saslMutex; // mutex to protect m_saslDone
         boost::condition_variable m_saslCv; // to signal completion of SASL exchange
 
+        // Used for encryption and is set when server notifies in first handshake response.
+        EncryptionContext m_encryptionCtxt;
+
+        // Function pointer for read and send handler. By default these are referred to handler for plain message read/send. When encryption is enabled
+        // then after successful handshake these pointers refer to handler for encrypted message read/send over wire.
+        status_t (DrillClientImpl::*m_fpCurrentReadMsgHandler)(ByteBuf_t inBuf, AllocatedBufferPtr* allocatedBuffer, rpc::InBoundRpcMessage& msg);
+        connectionStatus_t (DrillClientImpl::*m_fpCurrentSendHandler)();
+
         std::string m_connectStr; 
 
         // 

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/rpcMessage.cpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/rpcMessage.cpp b/contrib/native/client/src/clientlib/rpcMessage.cpp
index 13cd7a8..f64167f 100644
--- a/contrib/native/client/src/clientlib/rpcMessage.cpp
+++ b/contrib/native/client/src/clientlib/rpcMessage.cpp
@@ -47,7 +47,7 @@ std::size_t lengthDecode(const uint8_t* buf, uint32_t& length) {
 
     // read the frame to get the length of the message and then
 
-    CodedInputStream cis(buf, 5); // read 5 bytes at most
+    CodedInputStream cis(buf, LEN_PREFIX_BUFLEN); // read LEN_PREFIX_BUFLEN bytes at most
 
     int startPos(cis.CurrentPosition()); // for debugging
     if (!cis.ReadVarint32(&length)) {

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/rpcMessage.hpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/rpcMessage.hpp b/contrib/native/client/src/clientlib/rpcMessage.hpp
index 15487e9..43bcaeb 100644
--- a/contrib/native/client/src/clientlib/rpcMessage.hpp
+++ b/contrib/native/client/src/clientlib/rpcMessage.hpp
@@ -54,7 +54,6 @@ std::size_t lengthDecode(const uint8_t* buf, uint32_t& length);
 bool decode(const uint8_t* buf, int length, InBoundRpcMessage& msg);
 
 bool encode(DataBuf& buf, const OutBoundRpcMessage& msg);
-
 } // namespace rpc
 } // namespace Drill
 

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/saslAuthenticatorImpl.cpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/saslAuthenticatorImpl.cpp b/contrib/native/client/src/clientlib/saslAuthenticatorImpl.cpp
index e7e2ba5..c5dc3ac 100644
--- a/contrib/native/client/src/clientlib/saslAuthenticatorImpl.cpp
+++ b/contrib/native/client/src/clientlib/saslAuthenticatorImpl.cpp
@@ -32,6 +32,7 @@ static const std::string DEFAULT_SERVICE_NAME = "drill";
 static const std::string KERBEROS_SIMPLE_NAME = "kerberos";
 static const std::string KERBEROS_SASL_NAME = "gssapi";
 static const std::string PLAIN_NAME = "plain";
+static const int PREFERRED_MIN_SSF = 56;
 
 const std::map<std::string, std::string> SaslAuthenticatorImpl::MECHANISM_MAPPING = boost::assign::map_list_of
     (KERBEROS_SIMPLE_NAME, KERBEROS_SASL_NAME)
@@ -42,8 +43,7 @@ boost::mutex SaslAuthenticatorImpl::s_mutex;
 bool SaslAuthenticatorImpl::s_initialized = false;
 
 SaslAuthenticatorImpl::SaslAuthenticatorImpl(const DrillUserProperties* const properties) :
-    m_pUserProperties(properties), m_pConnection(NULL), m_ppwdSecret(NULL) {
-
+    m_pUserProperties(properties), m_pConnection(NULL), m_ppwdSecret(NULL), m_pEncryptCtxt(NULL) {
     if (!s_initialized) {
         boost::lock_guard<boost::mutex> lock(SaslAuthenticatorImpl::s_mutex);
         if (!s_initialized) {
@@ -85,6 +85,9 @@ SaslAuthenticatorImpl::~SaslAuthenticatorImpl() {
         sasl_dispose(&m_pConnection);
     }
     m_pConnection = NULL;
+
+    // Memory is owned by DrillClientImpl object
+    m_pEncryptCtxt = NULL;
 }
 
 typedef int (*sasl_callback_proc_t)(void); // see sasl_callback_ft
@@ -109,8 +112,14 @@ int SaslAuthenticatorImpl::passwordCallback(sasl_conn_t *conn, void *context, in
     return SASL_OK;
 }
 
-int SaslAuthenticatorImpl::init(const std::vector<std::string>& mechanisms, exec::shared::SaslMessage& response) {
-    // find and set parameters
+int SaslAuthenticatorImpl::init(const std::vector<std::string>& mechanisms, exec::shared::SaslMessage& response,
+                                EncryptionContext* const encryptCtxt) {
+
+    // EncryptionContext should not be NULL here.
+    assert(encryptCtxt != NULL);
+    m_pEncryptCtxt = encryptCtxt;
+
+	// find and set parameters
     std::string authMechanismToUse;
     std::string serviceName;
     std::string serviceHost;
@@ -163,6 +172,9 @@ int SaslAuthenticatorImpl::init(const std::vector<std::string>& mechanisms, exec
                                       << saslResult << std::endl;)
     if (saslResult != SASL_OK) return saslResult;
 
+    // set the security properties
+    setSecurityProps();
+
     // initiate; for now, pass in only one mechanism
     const char *out;
     unsigned outlen;
@@ -204,4 +216,103 @@ int SaslAuthenticatorImpl::step(const exec::shared::SaslMessage& challenge, exec
     return saslResult;
 }
 
+/*
+ * Verify that the negotiated value is correct as per system configurations. Also retrieves and set the rawWrapSendSize
+ */
+int SaslAuthenticatorImpl::verifyAndUpdateSaslProps() {
+    const int* negotiatedValue;
+    int result = SASL_OK;
+
+    if(SASL_OK != (result = sasl_getprop(m_pConnection, SASL_SSF, reinterpret_cast<const void **>(&negotiatedValue)))) {
+        return result;
+    }
+
+    // If the negotiated SSF value is less than required one that means we have negotiated for weaker security level.
+    if(*negotiatedValue < PREFERRED_MIN_SSF) {
+        DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "SaslAuthenticatorImpl::verifyAndUpdateSaslProps: "
+                                          << "Negotiated SSF parameter:" << *negotiatedValue
+                                          << " is less than Preferred one: " << PREFERRED_MIN_SSF << std::endl;)
+        result = SASL_BADPARAM;
+        return result;
+    }
+
+    if(SASL_OK != (result = sasl_getprop(m_pConnection, SASL_MAXOUTBUF,
+                                         reinterpret_cast<const void **>(&negotiatedValue)))) {
+        return result;
+    }
+
+    DRILL_MT_LOG(DRILL_LOG(LOG_DEBUG) << "SaslAuthenticatorImpl::verifyAndUpdateSaslProps: "
+                                      << "Negotiated Raw Wrap Buffer size: " << *negotiatedValue << std::endl;)
+
+    m_pEncryptCtxt->setWrapSizeLimit(*negotiatedValue);
+    return result;
+}
+
+/*
+ *  Set the security properties structure with all the needed parameters for encryption so that
+ *  a proper mechanism with and cipher is chosen after handshake.
+ *
+ *  PREFERRED_MIN_SSF is chosen to be 56 since that is the max_ssf supported by gssapi. We want 
+ *  stronger cipher algorithm to be used all the time (preferably AES-256), so leaving MAX_SSF as UINT_MAX
+ */
+void SaslAuthenticatorImpl::setSecurityProps() const{
+
+    if(m_pEncryptCtxt->isEncryptionReqd()) {
+        // set the security properties.
+        sasl_security_properties_t secprops;
+        secprops.min_ssf = PREFERRED_MIN_SSF;
+        secprops.max_ssf = UINT_MAX;
+        secprops.maxbufsize = m_pEncryptCtxt->getMaxWrappedSize();
+        secprops.property_names = NULL;
+        secprops.property_values = NULL;
+        // Only specify NOPLAINTEXT for encryption since the mechanism is selected based on name not
+        // the security properties configured here.
+        secprops.security_flags = SASL_SEC_NOPLAINTEXT;
+
+        // Set the security properties in the connection context.
+        sasl_setprop(m_pConnection, SASL_SEC_PROPS, &secprops);
+    }
+}
+
+/*
+ * Encodes the input data by calling the sasl_encode provided by Cyrus-SASL library which internally calls
+ * the wrap function of the chosen mechanism. The output buffer will have first 4 octets as the length of
+ * encrypted data in network byte order.
+ *
+ * Parameters:
+ *      dataToWrap      -   in param    -   pointer to data buffer to encrypt.
+ *      dataToWrapLen   -   in param    -   length of data buffer to encrypt.
+ *      output          -   out param   -   pointer to data buffer with encrypted data. Allocated by Cyrus-SASL
+ *      wrappedLen      -   out param   -   length of data after encryption
+ * Returns:
+ *      SASL_OK         - success (returns input if no layer negotiated)
+ *      SASL_NOTDONE    - security layer negotiation not finished
+ *      SASL_BADPARAM   - inputlen is greater than the SASL_MAXOUTBUF
+ */
+int SaslAuthenticatorImpl::wrap(const char* dataToWrap, const int& dataToWrapLen, const char** output,
+                                uint32_t& wrappedLen) {
+    return sasl_encode(m_pConnection, dataToWrap, dataToWrapLen, output, &wrappedLen);
+}
+
+/*
+ * Decodes the input data by calling the sasl_decode provided by Cyrus-SASL library which internally calls
+ * the wrap function of the chosen mechanism. The input buffer will have first 4 octets as the length of
+ * encrypted data in network byte order.
+ *
+ * Parameters:
+ *      dataToUnWrap      -   in param    -   pointer to data buffer to decrypt.
+ *      dataToUnWrapLen   -   in param    -   length of data buffer to decrypt.
+ *      output            -   out param   -   pointer to data buffer with decrypted data. Allocated by Cyrus-SASL
+ *      unWrappedLen      -   out param   -   length of data after decryption
+ * Returns:
+ *      SASL_OK         - success (returns input if no layer negotiated)
+ *      SASL_NOTDONE    - security layer negotiation not finished
+ *      SASL_BADPARAM   - inputlen is greater than the SASL_MAXOUTBUF
+ */
+int SaslAuthenticatorImpl::unwrap(const char* dataToUnWrap, const int& dataToUnWrapLen, const char** output,
+                                  uint32_t& unWrappedLen) {
+    return sasl_decode(m_pConnection, dataToUnWrap, dataToUnWrapLen, output, &unWrappedLen);
+}
+
+
 } /* namespace Drill */

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/saslAuthenticatorImpl.hpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/saslAuthenticatorImpl.hpp b/contrib/native/client/src/clientlib/saslAuthenticatorImpl.hpp
index 5e36ee1..53fe4e3 100644
--- a/contrib/native/client/src/clientlib/saslAuthenticatorImpl.hpp
+++ b/contrib/native/client/src/clientlib/saslAuthenticatorImpl.hpp
@@ -24,6 +24,7 @@
 #include <vector>
 #include "drill/drillClient.hpp"
 #include "UserBitShared.pb.h"
+#include "utils.hpp"
 
 #include "sasl/sasl.h"
 #include "sasl/saslplug.h"
@@ -38,10 +39,17 @@ public:
 
     ~SaslAuthenticatorImpl();
 
-    int init(const std::vector<std::string>& mechanisms, exec::shared::SaslMessage& response);
+    int init(const std::vector<std::string>& mechanisms, exec::shared::SaslMessage& response,
+             EncryptionContext* const encryptCtxt);
 
     int step(const exec::shared::SaslMessage& challenge, exec::shared::SaslMessage& response) const;
 
+    int verifyAndUpdateSaslProps();
+
+    int wrap(const char* dataToWrap, const int& dataToWrapLen, const char** output, uint32_t& wrappedLen);
+
+    int unwrap(const char* dataToUnWrap, const int& dataToUnWrapLen, const char** output, uint32_t& unWrappedLen);
+
 private:
 
     static const std::map<std::string, std::string> MECHANISM_MAPPING;
@@ -53,11 +61,13 @@ private:
     sasl_conn_t *m_pConnection;
     std::string m_username;
     sasl_secret_t *m_ppwdSecret;
+    EncryptionContext *m_pEncryptCtxt;
 
     static int passwordCallback(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret);
 
     static int userNameCallback(void *context, int id, const char **result, unsigned int *len);
 
+    void setSecurityProps() const;
 };
 
 } /* namespace Drill */

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/utils.cpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/utils.cpp b/contrib/native/client/src/clientlib/utils.cpp
index d3c8f08..11aa2c2 100644
--- a/contrib/native/client/src/clientlib/utils.cpp
+++ b/contrib/native/client/src/clientlib/utils.cpp
@@ -111,4 +111,53 @@ AllocatedBuffer::~AllocatedBuffer(){
     m_bufSize = 0;
 }
 
+EncryptionContext::EncryptionContext(const bool& encryptionReqd, const int& maxWrappedSize, const int& wrapSizeLimit) {
+    this->m_bEncryptionReqd = encryptionReqd;
+    this->m_maxWrappedSize = maxWrappedSize;
+    this->m_wrapSizeLimit = wrapSizeLimit;
+}
+
+EncryptionContext::EncryptionContext() {
+    this->m_bEncryptionReqd = false;
+    this->m_maxWrappedSize = 65536;
+    this->m_wrapSizeLimit = 0;
+}
+
+void EncryptionContext::setEncryptionReqd(const bool& encryptionReqd) {
+    this->m_bEncryptionReqd = encryptionReqd;
+}
+
+void EncryptionContext::setMaxWrappedSize(const int& maxWrappedSize) {
+    this->m_maxWrappedSize = maxWrappedSize;
+}
+
+void EncryptionContext::setWrapSizeLimit(const int& wrapSizeLimit) {
+    this->m_wrapSizeLimit = wrapSizeLimit;
+}
+
+bool EncryptionContext::isEncryptionReqd() const {
+    return m_bEncryptionReqd;
+}
+
+int EncryptionContext::getMaxWrappedSize() const {
+    return m_maxWrappedSize;
+}
+
+int EncryptionContext::getWrapSizeLimit() const {
+    return m_wrapSizeLimit;
+}
+
+void EncryptionContext::reset() {
+    this->m_bEncryptionReqd = false;
+    this->m_maxWrappedSize = 65536;
+    this->m_wrapSizeLimit = 0;
+}
+
+std::ostream& operator<<(std::ostream &contextStream, const EncryptionContext& context) {
+    contextStream << " Encryption: " << (context.isEncryptionReqd() ? "enabled" : "disabled");
+    contextStream << " ,MaxWrappedSize: " << context.getMaxWrappedSize();
+    contextStream << " ,WrapSizeLimit: " << context.getWrapSizeLimit();
+    return contextStream;
+}
+
 } // namespace 

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/clientlib/utils.hpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/clientlib/utils.hpp b/contrib/native/client/src/clientlib/utils.hpp
index 4cd8fa5..d30794c 100644
--- a/contrib/native/client/src/clientlib/utils.hpp
+++ b/contrib/native/client/src/clientlib/utils.hpp
@@ -98,6 +98,38 @@ class DECLSPEC_DRILL_CLIENT Utils{
 
 }; // Utils
 
+/*
+ * Encryption related configuration parameters. The member's are updated with value received from server
+ * and also after the SASL Handshake is done.
+ */
+class EncryptionContext {
+
+	bool m_bEncryptionReqd;
+	int m_maxWrappedSize;
+	int m_wrapSizeLimit;
+
+public:
+	EncryptionContext();
+
+	EncryptionContext(const bool& encryptionReqd, const int& maxWrappedSize, const int& wrapSizeLimit);
+
+	void setEncryptionReqd(const bool& encryptionReqd);
+
+	void setMaxWrappedSize(const int& maxWrappedSize);
+
+	void setWrapSizeLimit(const int& wrapSizeLimit);
+
+	bool isEncryptionReqd() const;
+
+	int getMaxWrappedSize() const;
+
+	int getWrapSizeLimit() const;
+
+	void reset();
+
+	friend std::ostream& operator<<(std::ostream &contextStream, const EncryptionContext& context);
+};
+
 } // namespace Drill
 
 #endif

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/include/drill/common.hpp
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/include/drill/common.hpp b/contrib/native/client/src/include/drill/common.hpp
index ed0a1ed..5401c75 100644
--- a/contrib/native/client/src/include/drill/common.hpp
+++ b/contrib/native/client/src/include/drill/common.hpp
@@ -56,6 +56,7 @@
 
 #define LENGTH_PREFIX_MAX_LENGTH 5
 #define LEN_PREFIX_BUFLEN LENGTH_PREFIX_MAX_LENGTH
+#define ENCRYPT_LEN_PREFIX_BUFLEN 4
 
 #define MAX_CONNECT_STR 4096
 #define MAX_SOCK_RD_BUFSIZE  1024
@@ -169,6 +170,7 @@ typedef enum{
 #define USERPROP_AUTH_MECHANISM "auth"
 #define USERPROP_SERVICE_NAME "service_name"
 #define USERPROP_SERVICE_HOST "service_host"
+#define USERPROP_SASL_ENCRYPT "sasl_encrypt"
 
 // Bitflags to describe user properties
 // Used in DrillUserProperties::USER_PROPERTIES


[5/6] drill git commit: DRILL-4335: Apache Drill should support network encryption.

Posted by am...@apache.org.
http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/protobuf/User.pb.cc
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/protobuf/User.pb.cc b/contrib/native/client/src/protobuf/User.pb.cc
index be3f001..e2ae3d1 100644
--- a/contrib/native/client/src/protobuf/User.pb.cc
+++ b/contrib/native/client/src/protobuf/User.pb.cc
@@ -269,7 +269,7 @@ void protobuf_AssignDesc_User_2eproto() {
       ::google::protobuf::MessageFactory::generated_factory(),
       sizeof(QueryPlanFragments));
   BitToUserHandshake_descriptor_ = file->message_type(7);
-  static const int BitToUserHandshake_offsets_[7] = {
+  static const int BitToUserHandshake_offsets_[9] = {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, rpc_version_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, status_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, errorid_),
@@ -277,6 +277,8 @@ void protobuf_AssignDesc_User_2eproto() {
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, server_infos_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, authenticationmechanisms_),
     GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, supported_methods_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, encrypted_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BitToUserHandshake, maxwrappedsize_),
   };
   BitToUserHandshake_reflection_ =
     new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -952,198 +954,200 @@ void protobuf_AddDesc_User_2eproto() {
     "ed.QueryResult.QueryState\022&\n\010query_id\030\002 "
     "\001(\0132\024.exec.shared.QueryId\0221\n\tfragments\030\003"
     " \003(\0132\036.exec.bit.control.PlanFragment\022(\n\005"
-    "error\030\004 \001(\0132\031.exec.shared.DrillPBError\"\200"
+    "error\030\004 \001(\0132\031.exec.shared.DrillPBError\"\253"
     "\002\n\022BitToUserHandshake\022\023\n\013rpc_version\030\002 \001"
     "(\005\022*\n\006status\030\003 \001(\0162\032.exec.user.Handshake"
     "Status\022\017\n\007errorId\030\004 \001(\t\022\024\n\014errorMessage\030"
     "\005 \001(\t\0221\n\014server_infos\030\006 \001(\0132\033.exec.user."
     "RpcEndpointInfos\022 \n\030authenticationMechan"
     "isms\030\007 \003(\t\022-\n\021supported_methods\030\010 \003(\0162\022."
-    "exec.user.RpcType\"-\n\nLikeFilter\022\017\n\007patte"
-    "rn\030\001 \001(\t\022\016\n\006escape\030\002 \001(\t\"D\n\016GetCatalogsR"
-    "eq\0222\n\023catalog_name_filter\030\001 \001(\0132\025.exec.u"
-    "ser.LikeFilter\"M\n\017CatalogMetadata\022\024\n\014cat"
-    "alog_name\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022\017\n\007"
-    "connect\030\003 \001(\t\"\223\001\n\017GetCatalogsResp\022(\n\006sta"
-    "tus\030\001 \001(\0162\030.exec.user.RequestStatus\022,\n\010c"
-    "atalogs\030\002 \003(\0132\032.exec.user.CatalogMetadat"
-    "a\022(\n\005error\030\003 \001(\0132\031.exec.shared.DrillPBEr"
-    "ror\"v\n\rGetSchemasReq\0222\n\023catalog_name_fil"
-    "ter\030\001 \001(\0132\025.exec.user.LikeFilter\0221\n\022sche"
-    "ma_name_filter\030\002 \001(\0132\025.exec.user.LikeFil"
-    "ter\"i\n\016SchemaMetadata\022\024\n\014catalog_name\030\001 "
-    "\001(\t\022\023\n\013schema_name\030\002 \001(\t\022\r\n\005owner\030\003 \001(\t\022"
-    "\014\n\004type\030\004 \001(\t\022\017\n\007mutable\030\005 \001(\t\"\220\001\n\016GetSc"
-    "hemasResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Re"
-    "questStatus\022*\n\007schemas\030\002 \003(\0132\031.exec.user"
-    ".SchemaMetadata\022(\n\005error\030\003 \001(\0132\031.exec.sh"
-    "ared.DrillPBError\"\302\001\n\014GetTablesReq\0222\n\023ca"
-    "talog_name_filter\030\001 \001(\0132\025.exec.user.Like"
-    "Filter\0221\n\022schema_name_filter\030\002 \001(\0132\025.exe"
-    "c.user.LikeFilter\0220\n\021table_name_filter\030\003"
-    " \001(\0132\025.exec.user.LikeFilter\022\031\n\021table_typ"
-    "e_filter\030\004 \003(\t\"\\\n\rTableMetadata\022\024\n\014catal"
-    "og_name\030\001 \001(\t\022\023\n\013schema_name\030\002 \001(\t\022\022\n\nta"
-    "ble_name\030\003 \001(\t\022\014\n\004type\030\004 \001(\t\"\215\001\n\rGetTabl"
-    "esResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Reque"
-    "stStatus\022(\n\006tables\030\002 \003(\0132\030.exec.user.Tab"
-    "leMetadata\022(\n\005error\030\003 \001(\0132\031.exec.shared."
-    "DrillPBError\"\333\001\n\rGetColumnsReq\0222\n\023catalo"
-    "g_name_filter\030\001 \001(\0132\025.exec.user.LikeFilt"
-    "er\0221\n\022schema_name_filter\030\002 \001(\0132\025.exec.us"
-    "er.LikeFilter\0220\n\021table_name_filter\030\003 \001(\013"
-    "2\025.exec.user.LikeFilter\0221\n\022column_name_f"
-    "ilter\030\004 \001(\0132\025.exec.user.LikeFilter\"\251\003\n\016C"
-    "olumnMetadata\022\024\n\014catalog_name\030\001 \001(\t\022\023\n\013s"
-    "chema_name\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022\023\n\013"
-    "column_name\030\004 \001(\t\022\030\n\020ordinal_position\030\005 "
-    "\001(\005\022\025\n\rdefault_value\030\006 \001(\t\022\023\n\013is_nullabl"
-    "e\030\007 \001(\010\022\021\n\tdata_type\030\010 \001(\t\022\027\n\017char_max_l"
-    "ength\030\t \001(\005\022\031\n\021char_octet_length\030\n \001(\005\022\031"
-    "\n\021numeric_precision\030\013 \001(\005\022\037\n\027numeric_pre"
-    "cision_radix\030\014 \001(\005\022\025\n\rnumeric_scale\030\r \001("
-    "\005\022\033\n\023date_time_precision\030\016 \001(\005\022\025\n\rinterv"
-    "al_type\030\017 \001(\t\022\032\n\022interval_precision\030\020 \001("
-    "\005\022\023\n\013column_size\030\021 \001(\005\"\220\001\n\016GetColumnsRes"
-    "p\022(\n\006status\030\001 \001(\0162\030.exec.user.RequestSta"
-    "tus\022*\n\007columns\030\002 \003(\0132\031.exec.user.ColumnM"
-    "etadata\022(\n\005error\030\003 \001(\0132\031.exec.shared.Dri"
-    "llPBError\"/\n\032CreatePreparedStatementReq\022"
-    "\021\n\tsql_query\030\001 \001(\t\"\326\003\n\024ResultColumnMetad"
-    "ata\022\024\n\014catalog_name\030\001 \001(\t\022\023\n\013schema_name"
-    "\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022\023\n\013column_nam"
-    "e\030\004 \001(\t\022\r\n\005label\030\005 \001(\t\022\021\n\tdata_type\030\006 \001("
-    "\t\022\023\n\013is_nullable\030\007 \001(\010\022\021\n\tprecision\030\010 \001("
-    "\005\022\r\n\005scale\030\t \001(\005\022\016\n\006signed\030\n \001(\010\022\024\n\014disp"
-    "lay_size\030\013 \001(\005\022\022\n\nis_aliased\030\014 \001(\010\0225\n\rse"
-    "archability\030\r \001(\0162\036.exec.user.ColumnSear"
-    "chability\0223\n\014updatability\030\016 \001(\0162\035.exec.u"
-    "ser.ColumnUpdatability\022\026\n\016auto_increment"
-    "\030\017 \001(\010\022\030\n\020case_sensitivity\030\020 \001(\010\022\020\n\010sort"
-    "able\030\021 \001(\010\022\022\n\nclass_name\030\022 \001(\t\022\023\n\013is_cur"
-    "rency\030\024 \001(\010\".\n\027PreparedStatementHandle\022\023"
-    "\n\013server_info\030\001 \001(\014\"\200\001\n\021PreparedStatemen"
-    "t\0220\n\007columns\030\001 \003(\0132\037.exec.user.ResultCol"
-    "umnMetadata\0229\n\rserver_handle\030\002 \001(\0132\".exe"
-    "c.user.PreparedStatementHandle\"\253\001\n\033Creat"
-    "ePreparedStatementResp\022(\n\006status\030\001 \001(\0162\030"
-    ".exec.user.RequestStatus\0228\n\022prepared_sta"
-    "tement\030\002 \001(\0132\034.exec.user.PreparedStateme"
-    "nt\022(\n\005error\030\003 \001(\0132\031.exec.shared.DrillPBE"
-    "rror\"\022\n\020GetServerMetaReq\"P\n\016ConvertSuppo"
-    "rt\022\037\n\004from\030\001 \002(\0162\021.common.MinorType\022\035\n\002t"
-    "o\030\002 \002(\0162\021.common.MinorType\"\223\001\n\021GetServer"
-    "MetaResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Req"
-    "uestStatus\022*\n\013server_meta\030\002 \001(\0132\025.exec.u"
-    "ser.ServerMeta\022(\n\005error\030\003 \001(\0132\031.exec.sha"
-    "red.DrillPBError\"\377\r\n\nServerMeta\022\035\n\025all_t"
-    "ables_selectable\030\001 \001(\010\022%\n\035blob_included_"
-    "in_max_row_size\030\002 \001(\010\022\030\n\020catalog_at_star"
-    "t\030\003 \001(\010\022\031\n\021catalog_separator\030\004 \001(\t\022\024\n\014ca"
-    "talog_term\030\005 \001(\t\0222\n\017collate_support\030\006 \003("
-    "\0162\031.exec.user.CollateSupport\022!\n\031column_a"
-    "liasing_supported\030\007 \001(\010\0222\n\017convert_suppo"
-    "rt\030\010 \003(\0132\031.exec.user.ConvertSupport\022E\n\031c"
-    "orrelation_names_support\030\t \001(\0162\".exec.us"
-    "er.CorrelationNamesSupport\022\033\n\023date_time_"
-    "functions\030\n \003(\t\022F\n\032date_time_literals_su"
-    "pport\030\013 \003(\0162\".exec.user.DateTimeLiterals"
-    "Support\0223\n\020group_by_support\030\014 \001(\0162\031.exec"
-    ".user.GroupBySupport\0226\n\021identifier_casin"
-    "g\030\r \001(\0162\033.exec.user.IdentifierCasing\022\037\n\027"
-    "identifier_quote_string\030\016 \001(\t\022$\n\034like_es"
-    "cape_clause_supported\030\017 \001(\010\022!\n\031max_binar"
-    "y_literal_length\030\020 \001(\r\022\037\n\027max_catalog_na"
-    "me_length\030\021 \001(\r\022\037\n\027max_char_literal_leng"
-    "th\030\022 \001(\r\022\036\n\026max_column_name_length\030\023 \001(\r"
-    "\022\037\n\027max_columns_in_group_by\030\024 \001(\r\022\037\n\027max"
-    "_columns_in_order_by\030\025 \001(\r\022\035\n\025max_column"
-    "s_in_select\030\026 \001(\r\022\036\n\026max_cursor_name_len"
-    "gth\030\027 \001(\r\022\034\n\024max_logical_lob_size\030\030 \001(\r\022"
-    "\024\n\014max_row_size\030\031 \001(\r\022\036\n\026max_schema_name"
-    "_length\030\032 \001(\r\022\034\n\024max_statement_length\030\033 "
-    "\001(\r\022\026\n\016max_statements\030\034 \001(\r\022\035\n\025max_table"
-    "_name_length\030\035 \001(\r\022\034\n\024max_tables_in_sele"
-    "ct\030\036 \001(\r\022\034\n\024max_user_name_length\030\037 \001(\r\0220"
-    "\n\016null_collation\030  \001(\0162\030.exec.user.NullC"
-    "ollation\022&\n\036null_plus_non_null_equals_nu"
-    "ll\030! \001(\010\022\031\n\021numeric_functions\030\" \003(\t\0223\n\020o"
-    "rder_by_support\030# \003(\0162\031.exec.user.OrderB"
-    "ySupport\0227\n\022outer_join_support\030$ \003(\0162\033.e"
-    "xec.user.OuterJoinSupport\022=\n\030quoted_iden"
-    "tifier_casing\030% \001(\0162\033.exec.user.Identifi"
-    "erCasing\022\021\n\tread_only\030& \001(\010\022\023\n\013schema_te"
-    "rm\030\' \001(\t\022\034\n\024search_escape_string\030( \001(\t\022#"
-    "\n\033select_for_update_supported\030) \001(\010\022\032\n\022s"
-    "pecial_characters\030* \001(\t\022\024\n\014sql_keywords\030"
-    "+ \003(\t\022\030\n\020string_functions\030, \003(\t\0224\n\020subqu"
-    "ery_support\030- \003(\0162\032.exec.user.SubQuerySu"
-    "pport\022\030\n\020system_functions\030. \003(\t\022\022\n\ntable"
-    "_term\030/ \001(\t\022\035\n\025transaction_supported\0300 \001"
-    "(\010\022.\n\runion_support\0301 \003(\0162\027.exec.user.Un"
-    "ionSupport\"\353\001\n\010RunQuery\0221\n\014results_mode\030"
-    "\001 \001(\0162\033.exec.user.QueryResultsMode\022$\n\004ty"
-    "pe\030\002 \001(\0162\026.exec.shared.QueryType\022\014\n\004plan"
-    "\030\003 \001(\t\0221\n\tfragments\030\004 \003(\0132\036.exec.bit.con"
-    "trol.PlanFragment\022E\n\031prepared_statement_"
-    "handle\030\005 \001(\0132\".exec.user.PreparedStateme"
-    "ntHandle*\320\003\n\007RpcType\022\r\n\tHANDSHAKE\020\000\022\007\n\003A"
-    "CK\020\001\022\013\n\007GOODBYE\020\002\022\r\n\tRUN_QUERY\020\003\022\020\n\014CANC"
-    "EL_QUERY\020\004\022\023\n\017REQUEST_RESULTS\020\005\022\027\n\023RESUM"
-    "E_PAUSED_QUERY\020\013\022\034\n\030GET_QUERY_PLAN_FRAGM"
-    "ENTS\020\014\022\020\n\014GET_CATALOGS\020\016\022\017\n\013GET_SCHEMAS\020"
-    "\017\022\016\n\nGET_TABLES\020\020\022\017\n\013GET_COLUMNS\020\021\022\035\n\031CR"
-    "EATE_PREPARED_STATEMENT\020\026\022\023\n\017GET_SERVER_"
-    "META\020\010\022\016\n\nQUERY_DATA\020\006\022\020\n\014QUERY_HANDLE\020\007"
-    "\022\030\n\024QUERY_PLAN_FRAGMENTS\020\r\022\014\n\010CATALOGS\020\022"
-    "\022\013\n\007SCHEMAS\020\023\022\n\n\006TABLES\020\024\022\013\n\007COLUMNS\020\025\022\026"
-    "\n\022PREPARED_STATEMENT\020\027\022\017\n\013SERVER_META\020\t\022"
-    "\020\n\014QUERY_RESULT\020\n\022\020\n\014SASL_MESSAGE\020\030*6\n\013S"
-    "aslSupport\022\030\n\024UNKNOWN_SASL_SUPPORT\020\000\022\r\n\t"
-    "SASL_AUTH\020\001*#\n\020QueryResultsMode\022\017\n\013STREA"
-    "M_FULL\020\001*q\n\017HandshakeStatus\022\013\n\007SUCCESS\020\001"
-    "\022\030\n\024RPC_VERSION_MISMATCH\020\002\022\017\n\013AUTH_FAILE"
-    "D\020\003\022\023\n\017UNKNOWN_FAILURE\020\004\022\021\n\rAUTH_REQUIRE"
-    "D\020\005*D\n\rRequestStatus\022\022\n\016UNKNOWN_STATUS\020\000"
-    "\022\006\n\002OK\020\001\022\n\n\006FAILED\020\002\022\013\n\007TIMEOUT\020\003*Y\n\023Col"
-    "umnSearchability\022\031\n\025UNKNOWN_SEARCHABILIT"
-    "Y\020\000\022\010\n\004NONE\020\001\022\010\n\004CHAR\020\002\022\n\n\006NUMBER\020\003\022\007\n\003A"
-    "LL\020\004*K\n\022ColumnUpdatability\022\030\n\024UNKNOWN_UP"
-    "DATABILITY\020\000\022\r\n\tREAD_ONLY\020\001\022\014\n\010WRITABLE\020"
-    "\002*1\n\016CollateSupport\022\016\n\nCS_UNKNOWN\020\000\022\017\n\013C"
-    "S_GROUP_BY\020\001*J\n\027CorrelationNamesSupport\022"
-    "\013\n\007CN_NONE\020\001\022\026\n\022CN_DIFFERENT_NAMES\020\002\022\n\n\006"
-    "CN_ANY\020\003*\271\003\n\027DateTimeLiteralsSupport\022\016\n\n"
-    "DL_UNKNOWN\020\000\022\013\n\007DL_DATE\020\001\022\013\n\007DL_TIME\020\002\022\020"
-    "\n\014DL_TIMESTAMP\020\003\022\024\n\020DL_INTERVAL_YEAR\020\004\022\025"
-    "\n\021DL_INTERVAL_MONTH\020\005\022\023\n\017DL_INTERVAL_DAY"
-    "\020\006\022\024\n\020DL_INTERVAL_HOUR\020\007\022\026\n\022DL_INTERVAL_"
-    "MINUTE\020\010\022\026\n\022DL_INTERVAL_SECOND\020\t\022\035\n\031DL_I"
-    "NTERVAL_YEAR_TO_MONTH\020\n\022\033\n\027DL_INTERVAL_D"
-    "AY_TO_HOUR\020\013\022\035\n\031DL_INTERVAL_DAY_TO_MINUT"
-    "E\020\014\022\035\n\031DL_INTERVAL_DAY_TO_SECOND\020\r\022\036\n\032DL"
-    "_INTERVAL_HOUR_TO_MINUTE\020\016\022\036\n\032DL_INTERVA"
-    "L_HOUR_TO_SECOND\020\017\022 \n\034DL_INTERVAL_MINUTE"
-    "_TO_SECOND\020\020*Y\n\016GroupBySupport\022\013\n\007GB_NON"
-    "E\020\001\022\022\n\016GB_SELECT_ONLY\020\002\022\024\n\020GB_BEYOND_SEL"
-    "ECT\020\003\022\020\n\014GB_UNRELATED\020\004*x\n\020IdentifierCas"
-    "ing\022\016\n\nIC_UNKNOWN\020\000\022\023\n\017IC_STORES_LOWER\020\001"
-    "\022\023\n\017IC_STORES_MIXED\020\002\022\023\n\017IC_STORES_UPPER"
-    "\020\003\022\025\n\021IC_SUPPORTS_MIXED\020\004*X\n\rNullCollati"
-    "on\022\016\n\nNC_UNKNOWN\020\000\022\017\n\013NC_AT_START\020\001\022\r\n\tN"
-    "C_AT_END\020\002\022\013\n\007NC_HIGH\020\003\022\n\n\006NC_LOW\020\004*E\n\016O"
-    "rderBySupport\022\016\n\nOB_UNKNOWN\020\000\022\020\n\014OB_UNRE"
-    "LATED\020\001\022\021\n\rOB_EXPRESSION\020\002*\226\001\n\020OuterJoin"
-    "Support\022\016\n\nOJ_UNKNOWN\020\000\022\013\n\007OJ_LEFT\020\001\022\014\n\010"
-    "OJ_RIGHT\020\002\022\013\n\007OJ_FULL\020\003\022\r\n\tOJ_NESTED\020\004\022\022"
-    "\n\016OJ_NOT_ORDERED\020\005\022\014\n\010OJ_INNER\020\006\022\031\n\025OJ_A"
-    "LL_COMPARISON_OPS\020\007*\204\001\n\017SubQuerySupport\022"
-    "\016\n\nSQ_UNKNOWN\020\000\022\021\n\rSQ_CORRELATED\020\001\022\024\n\020SQ"
-    "_IN_COMPARISON\020\002\022\020\n\014SQ_IN_EXISTS\020\003\022\020\n\014SQ"
-    "_IN_INSERT\020\004\022\024\n\020SQ_IN_QUANTIFIED\020\005*;\n\014Un"
-    "ionSupport\022\r\n\tU_UNKNOWN\020\000\022\013\n\007U_UNION\020\001\022\017"
-    "\n\013U_UNION_ALL\020\002B+\n\033org.apache.drill.exec"
-    ".protoB\nUserProtosH\001", 8820);
+    "exec.user.RpcType\022\021\n\tencrypted\030\t \001(\010\022\026\n\016"
+    "maxWrappedSize\030\n \001(\005\"-\n\nLikeFilter\022\017\n\007pa"
+    "ttern\030\001 \001(\t\022\016\n\006escape\030\002 \001(\t\"D\n\016GetCatalo"
+    "gsReq\0222\n\023catalog_name_filter\030\001 \001(\0132\025.exe"
+    "c.user.LikeFilter\"M\n\017CatalogMetadata\022\024\n\014"
+    "catalog_name\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022"
+    "\017\n\007connect\030\003 \001(\t\"\223\001\n\017GetCatalogsResp\022(\n\006"
+    "status\030\001 \001(\0162\030.exec.user.RequestStatus\022,"
+    "\n\010catalogs\030\002 \003(\0132\032.exec.user.CatalogMeta"
+    "data\022(\n\005error\030\003 \001(\0132\031.exec.shared.DrillP"
+    "BError\"v\n\rGetSchemasReq\0222\n\023catalog_name_"
+    "filter\030\001 \001(\0132\025.exec.user.LikeFilter\0221\n\022s"
+    "chema_name_filter\030\002 \001(\0132\025.exec.user.Like"
+    "Filter\"i\n\016SchemaMetadata\022\024\n\014catalog_name"
+    "\030\001 \001(\t\022\023\n\013schema_name\030\002 \001(\t\022\r\n\005owner\030\003 \001"
+    "(\t\022\014\n\004type\030\004 \001(\t\022\017\n\007mutable\030\005 \001(\t\"\220\001\n\016Ge"
+    "tSchemasResp\022(\n\006status\030\001 \001(\0162\030.exec.user"
+    ".RequestStatus\022*\n\007schemas\030\002 \003(\0132\031.exec.u"
+    "ser.SchemaMetadata\022(\n\005error\030\003 \001(\0132\031.exec"
+    ".shared.DrillPBError\"\302\001\n\014GetTablesReq\0222\n"
+    "\023catalog_name_filter\030\001 \001(\0132\025.exec.user.L"
+    "ikeFilter\0221\n\022schema_name_filter\030\002 \001(\0132\025."
+    "exec.user.LikeFilter\0220\n\021table_name_filte"
+    "r\030\003 \001(\0132\025.exec.user.LikeFilter\022\031\n\021table_"
+    "type_filter\030\004 \003(\t\"\\\n\rTableMetadata\022\024\n\014ca"
+    "talog_name\030\001 \001(\t\022\023\n\013schema_name\030\002 \001(\t\022\022\n"
+    "\ntable_name\030\003 \001(\t\022\014\n\004type\030\004 \001(\t\"\215\001\n\rGetT"
+    "ablesResp\022(\n\006status\030\001 \001(\0162\030.exec.user.Re"
+    "questStatus\022(\n\006tables\030\002 \003(\0132\030.exec.user."
+    "TableMetadata\022(\n\005error\030\003 \001(\0132\031.exec.shar"
+    "ed.DrillPBError\"\333\001\n\rGetColumnsReq\0222\n\023cat"
+    "alog_name_filter\030\001 \001(\0132\025.exec.user.LikeF"
+    "ilter\0221\n\022schema_name_filter\030\002 \001(\0132\025.exec"
+    ".user.LikeFilter\0220\n\021table_name_filter\030\003 "
+    "\001(\0132\025.exec.user.LikeFilter\0221\n\022column_nam"
+    "e_filter\030\004 \001(\0132\025.exec.user.LikeFilter\"\251\003"
+    "\n\016ColumnMetadata\022\024\n\014catalog_name\030\001 \001(\t\022\023"
+    "\n\013schema_name\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022"
+    "\023\n\013column_name\030\004 \001(\t\022\030\n\020ordinal_position"
+    "\030\005 \001(\005\022\025\n\rdefault_value\030\006 \001(\t\022\023\n\013is_null"
+    "able\030\007 \001(\010\022\021\n\tdata_type\030\010 \001(\t\022\027\n\017char_ma"
+    "x_length\030\t \001(\005\022\031\n\021char_octet_length\030\n \001("
+    "\005\022\031\n\021numeric_precision\030\013 \001(\005\022\037\n\027numeric_"
+    "precision_radix\030\014 \001(\005\022\025\n\rnumeric_scale\030\r"
+    " \001(\005\022\033\n\023date_time_precision\030\016 \001(\005\022\025\n\rint"
+    "erval_type\030\017 \001(\t\022\032\n\022interval_precision\030\020"
+    " \001(\005\022\023\n\013column_size\030\021 \001(\005\"\220\001\n\016GetColumns"
+    "Resp\022(\n\006status\030\001 \001(\0162\030.exec.user.Request"
+    "Status\022*\n\007columns\030\002 \003(\0132\031.exec.user.Colu"
+    "mnMetadata\022(\n\005error\030\003 \001(\0132\031.exec.shared."
+    "DrillPBError\"/\n\032CreatePreparedStatementR"
+    "eq\022\021\n\tsql_query\030\001 \001(\t\"\326\003\n\024ResultColumnMe"
+    "tadata\022\024\n\014catalog_name\030\001 \001(\t\022\023\n\013schema_n"
+    "ame\030\002 \001(\t\022\022\n\ntable_name\030\003 \001(\t\022\023\n\013column_"
+    "name\030\004 \001(\t\022\r\n\005label\030\005 \001(\t\022\021\n\tdata_type\030\006"
+    " \001(\t\022\023\n\013is_nullable\030\007 \001(\010\022\021\n\tprecision\030\010"
+    " \001(\005\022\r\n\005scale\030\t \001(\005\022\016\n\006signed\030\n \001(\010\022\024\n\014d"
+    "isplay_size\030\013 \001(\005\022\022\n\nis_aliased\030\014 \001(\010\0225\n"
+    "\rsearchability\030\r \001(\0162\036.exec.user.ColumnS"
+    "earchability\0223\n\014updatability\030\016 \001(\0162\035.exe"
+    "c.user.ColumnUpdatability\022\026\n\016auto_increm"
+    "ent\030\017 \001(\010\022\030\n\020case_sensitivity\030\020 \001(\010\022\020\n\010s"
+    "ortable\030\021 \001(\010\022\022\n\nclass_name\030\022 \001(\t\022\023\n\013is_"
+    "currency\030\024 \001(\010\".\n\027PreparedStatementHandl"
+    "e\022\023\n\013server_info\030\001 \001(\014\"\200\001\n\021PreparedState"
+    "ment\0220\n\007columns\030\001 \003(\0132\037.exec.user.Result"
+    "ColumnMetadata\0229\n\rserver_handle\030\002 \001(\0132\"."
+    "exec.user.PreparedStatementHandle\"\253\001\n\033Cr"
+    "eatePreparedStatementResp\022(\n\006status\030\001 \001("
+    "\0162\030.exec.user.RequestStatus\0228\n\022prepared_"
+    "statement\030\002 \001(\0132\034.exec.user.PreparedStat"
+    "ement\022(\n\005error\030\003 \001(\0132\031.exec.shared.Drill"
+    "PBError\"\022\n\020GetServerMetaReq\"P\n\016ConvertSu"
+    "pport\022\037\n\004from\030\001 \002(\0162\021.common.MinorType\022\035"
+    "\n\002to\030\002 \002(\0162\021.common.MinorType\"\223\001\n\021GetSer"
+    "verMetaResp\022(\n\006status\030\001 \001(\0162\030.exec.user."
+    "RequestStatus\022*\n\013server_meta\030\002 \001(\0132\025.exe"
+    "c.user.ServerMeta\022(\n\005error\030\003 \001(\0132\031.exec."
+    "shared.DrillPBError\"\377\r\n\nServerMeta\022\035\n\025al"
+    "l_tables_selectable\030\001 \001(\010\022%\n\035blob_includ"
+    "ed_in_max_row_size\030\002 \001(\010\022\030\n\020catalog_at_s"
+    "tart\030\003 \001(\010\022\031\n\021catalog_separator\030\004 \001(\t\022\024\n"
+    "\014catalog_term\030\005 \001(\t\0222\n\017collate_support\030\006"
+    " \003(\0162\031.exec.user.CollateSupport\022!\n\031colum"
+    "n_aliasing_supported\030\007 \001(\010\0222\n\017convert_su"
+    "pport\030\010 \003(\0132\031.exec.user.ConvertSupport\022E"
+    "\n\031correlation_names_support\030\t \001(\0162\".exec"
+    ".user.CorrelationNamesSupport\022\033\n\023date_ti"
+    "me_functions\030\n \003(\t\022F\n\032date_time_literals"
+    "_support\030\013 \003(\0162\".exec.user.DateTimeLiter"
+    "alsSupport\0223\n\020group_by_support\030\014 \001(\0162\031.e"
+    "xec.user.GroupBySupport\0226\n\021identifier_ca"
+    "sing\030\r \001(\0162\033.exec.user.IdentifierCasing\022"
+    "\037\n\027identifier_quote_string\030\016 \001(\t\022$\n\034like"
+    "_escape_clause_supported\030\017 \001(\010\022!\n\031max_bi"
+    "nary_literal_length\030\020 \001(\r\022\037\n\027max_catalog"
+    "_name_length\030\021 \001(\r\022\037\n\027max_char_literal_l"
+    "ength\030\022 \001(\r\022\036\n\026max_column_name_length\030\023 "
+    "\001(\r\022\037\n\027max_columns_in_group_by\030\024 \001(\r\022\037\n\027"
+    "max_columns_in_order_by\030\025 \001(\r\022\035\n\025max_col"
+    "umns_in_select\030\026 \001(\r\022\036\n\026max_cursor_name_"
+    "length\030\027 \001(\r\022\034\n\024max_logical_lob_size\030\030 \001"
+    "(\r\022\024\n\014max_row_size\030\031 \001(\r\022\036\n\026max_schema_n"
+    "ame_length\030\032 \001(\r\022\034\n\024max_statement_length"
+    "\030\033 \001(\r\022\026\n\016max_statements\030\034 \001(\r\022\035\n\025max_ta"
+    "ble_name_length\030\035 \001(\r\022\034\n\024max_tables_in_s"
+    "elect\030\036 \001(\r\022\034\n\024max_user_name_length\030\037 \001("
+    "\r\0220\n\016null_collation\030  \001(\0162\030.exec.user.Nu"
+    "llCollation\022&\n\036null_plus_non_null_equals"
+    "_null\030! \001(\010\022\031\n\021numeric_functions\030\" \003(\t\0223"
+    "\n\020order_by_support\030# \003(\0162\031.exec.user.Ord"
+    "erBySupport\0227\n\022outer_join_support\030$ \003(\0162"
+    "\033.exec.user.OuterJoinSupport\022=\n\030quoted_i"
+    "dentifier_casing\030% \001(\0162\033.exec.user.Ident"
+    "ifierCasing\022\021\n\tread_only\030& \001(\010\022\023\n\013schema"
+    "_term\030\' \001(\t\022\034\n\024search_escape_string\030( \001("
+    "\t\022#\n\033select_for_update_supported\030) \001(\010\022\032"
+    "\n\022special_characters\030* \001(\t\022\024\n\014sql_keywor"
+    "ds\030+ \003(\t\022\030\n\020string_functions\030, \003(\t\0224\n\020su"
+    "bquery_support\030- \003(\0162\032.exec.user.SubQuer"
+    "ySupport\022\030\n\020system_functions\030. \003(\t\022\022\n\nta"
+    "ble_term\030/ \001(\t\022\035\n\025transaction_supported\030"
+    "0 \001(\010\022.\n\runion_support\0301 \003(\0162\027.exec.user"
+    ".UnionSupport\"\353\001\n\010RunQuery\0221\n\014results_mo"
+    "de\030\001 \001(\0162\033.exec.user.QueryResultsMode\022$\n"
+    "\004type\030\002 \001(\0162\026.exec.shared.QueryType\022\014\n\004p"
+    "lan\030\003 \001(\t\0221\n\tfragments\030\004 \003(\0132\036.exec.bit."
+    "control.PlanFragment\022E\n\031prepared_stateme"
+    "nt_handle\030\005 \001(\0132\".exec.user.PreparedStat"
+    "ementHandle*\320\003\n\007RpcType\022\r\n\tHANDSHAKE\020\000\022\007"
+    "\n\003ACK\020\001\022\013\n\007GOODBYE\020\002\022\r\n\tRUN_QUERY\020\003\022\020\n\014C"
+    "ANCEL_QUERY\020\004\022\023\n\017REQUEST_RESULTS\020\005\022\027\n\023RE"
+    "SUME_PAUSED_QUERY\020\013\022\034\n\030GET_QUERY_PLAN_FR"
+    "AGMENTS\020\014\022\020\n\014GET_CATALOGS\020\016\022\017\n\013GET_SCHEM"
+    "AS\020\017\022\016\n\nGET_TABLES\020\020\022\017\n\013GET_COLUMNS\020\021\022\035\n"
+    "\031CREATE_PREPARED_STATEMENT\020\026\022\023\n\017GET_SERV"
+    "ER_META\020\010\022\016\n\nQUERY_DATA\020\006\022\020\n\014QUERY_HANDL"
+    "E\020\007\022\030\n\024QUERY_PLAN_FRAGMENTS\020\r\022\014\n\010CATALOG"
+    "S\020\022\022\013\n\007SCHEMAS\020\023\022\n\n\006TABLES\020\024\022\013\n\007COLUMNS\020"
+    "\025\022\026\n\022PREPARED_STATEMENT\020\027\022\017\n\013SERVER_META"
+    "\020\t\022\020\n\014QUERY_RESULT\020\n\022\020\n\014SASL_MESSAGE\020\030*H"
+    "\n\013SaslSupport\022\030\n\024UNKNOWN_SASL_SUPPORT\020\000\022"
+    "\r\n\tSASL_AUTH\020\001\022\020\n\014SASL_PRIVACY\020\002*#\n\020Quer"
+    "yResultsMode\022\017\n\013STREAM_FULL\020\001*q\n\017Handsha"
+    "keStatus\022\013\n\007SUCCESS\020\001\022\030\n\024RPC_VERSION_MIS"
+    "MATCH\020\002\022\017\n\013AUTH_FAILED\020\003\022\023\n\017UNKNOWN_FAIL"
+    "URE\020\004\022\021\n\rAUTH_REQUIRED\020\005*D\n\rRequestStatu"
+    "s\022\022\n\016UNKNOWN_STATUS\020\000\022\006\n\002OK\020\001\022\n\n\006FAILED\020"
+    "\002\022\013\n\007TIMEOUT\020\003*Y\n\023ColumnSearchability\022\031\n"
+    "\025UNKNOWN_SEARCHABILITY\020\000\022\010\n\004NONE\020\001\022\010\n\004CH"
+    "AR\020\002\022\n\n\006NUMBER\020\003\022\007\n\003ALL\020\004*K\n\022ColumnUpdat"
+    "ability\022\030\n\024UNKNOWN_UPDATABILITY\020\000\022\r\n\tREA"
+    "D_ONLY\020\001\022\014\n\010WRITABLE\020\002*1\n\016CollateSupport"
+    "\022\016\n\nCS_UNKNOWN\020\000\022\017\n\013CS_GROUP_BY\020\001*J\n\027Cor"
+    "relationNamesSupport\022\013\n\007CN_NONE\020\001\022\026\n\022CN_"
+    "DIFFERENT_NAMES\020\002\022\n\n\006CN_ANY\020\003*\271\003\n\027DateTi"
+    "meLiteralsSupport\022\016\n\nDL_UNKNOWN\020\000\022\013\n\007DL_"
+    "DATE\020\001\022\013\n\007DL_TIME\020\002\022\020\n\014DL_TIMESTAMP\020\003\022\024\n"
+    "\020DL_INTERVAL_YEAR\020\004\022\025\n\021DL_INTERVAL_MONTH"
+    "\020\005\022\023\n\017DL_INTERVAL_DAY\020\006\022\024\n\020DL_INTERVAL_H"
+    "OUR\020\007\022\026\n\022DL_INTERVAL_MINUTE\020\010\022\026\n\022DL_INTE"
+    "RVAL_SECOND\020\t\022\035\n\031DL_INTERVAL_YEAR_TO_MON"
+    "TH\020\n\022\033\n\027DL_INTERVAL_DAY_TO_HOUR\020\013\022\035\n\031DL_"
+    "INTERVAL_DAY_TO_MINUTE\020\014\022\035\n\031DL_INTERVAL_"
+    "DAY_TO_SECOND\020\r\022\036\n\032DL_INTERVAL_HOUR_TO_M"
+    "INUTE\020\016\022\036\n\032DL_INTERVAL_HOUR_TO_SECOND\020\017\022"
+    " \n\034DL_INTERVAL_MINUTE_TO_SECOND\020\020*Y\n\016Gro"
+    "upBySupport\022\013\n\007GB_NONE\020\001\022\022\n\016GB_SELECT_ON"
+    "LY\020\002\022\024\n\020GB_BEYOND_SELECT\020\003\022\020\n\014GB_UNRELAT"
+    "ED\020\004*x\n\020IdentifierCasing\022\016\n\nIC_UNKNOWN\020\000"
+    "\022\023\n\017IC_STORES_LOWER\020\001\022\023\n\017IC_STORES_MIXED"
+    "\020\002\022\023\n\017IC_STORES_UPPER\020\003\022\025\n\021IC_SUPPORTS_M"
+    "IXED\020\004*X\n\rNullCollation\022\016\n\nNC_UNKNOWN\020\000\022"
+    "\017\n\013NC_AT_START\020\001\022\r\n\tNC_AT_END\020\002\022\013\n\007NC_HI"
+    "GH\020\003\022\n\n\006NC_LOW\020\004*E\n\016OrderBySupport\022\016\n\nOB"
+    "_UNKNOWN\020\000\022\020\n\014OB_UNRELATED\020\001\022\021\n\rOB_EXPRE"
+    "SSION\020\002*\226\001\n\020OuterJoinSupport\022\016\n\nOJ_UNKNO"
+    "WN\020\000\022\013\n\007OJ_LEFT\020\001\022\014\n\010OJ_RIGHT\020\002\022\013\n\007OJ_FU"
+    "LL\020\003\022\r\n\tOJ_NESTED\020\004\022\022\n\016OJ_NOT_ORDERED\020\005\022"
+    "\014\n\010OJ_INNER\020\006\022\031\n\025OJ_ALL_COMPARISON_OPS\020\007"
+    "*\204\001\n\017SubQuerySupport\022\016\n\nSQ_UNKNOWN\020\000\022\021\n\r"
+    "SQ_CORRELATED\020\001\022\024\n\020SQ_IN_COMPARISON\020\002\022\020\n"
+    "\014SQ_IN_EXISTS\020\003\022\020\n\014SQ_IN_INSERT\020\004\022\024\n\020SQ_"
+    "IN_QUANTIFIED\020\005*;\n\014UnionSupport\022\r\n\tU_UNK"
+    "NOWN\020\000\022\013\n\007U_UNION\020\001\022\017\n\013U_UNION_ALL\020\002B+\n\033"
+    "org.apache.drill.exec.protoB\nUserProtosH"
+    "\001", 8881);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "User.proto", &protobuf_RegisterTypes);
   Property::default_instance_ = new Property();
@@ -1262,6 +1266,7 @@ bool SaslSupport_IsValid(int value) {
   switch(value) {
     case 0:
     case 1:
+    case 2:
       return true;
     default:
       return false;
@@ -4044,6 +4049,8 @@ const int BitToUserHandshake::kErrorMessageFieldNumber;
 const int BitToUserHandshake::kServerInfosFieldNumber;
 const int BitToUserHandshake::kAuthenticationMechanismsFieldNumber;
 const int BitToUserHandshake::kSupportedMethodsFieldNumber;
+const int BitToUserHandshake::kEncryptedFieldNumber;
+const int BitToUserHandshake::kMaxWrappedSizeFieldNumber;
 #endif  // !_MSC_VER
 
 BitToUserHandshake::BitToUserHandshake()
@@ -4068,6 +4075,8 @@ void BitToUserHandshake::SharedCtor() {
   errorid_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   errormessage_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
   server_infos_ = NULL;
+  encrypted_ = false;
+  maxwrappedsize_ = 0;
   ::memset(_has_bits_, 0, sizeof(_has_bits_));
 }
 
@@ -4125,6 +4134,10 @@ void BitToUserHandshake::Clear() {
     if (has_server_infos()) {
       if (server_infos_ != NULL) server_infos_->::exec::user::RpcEndpointInfos::Clear();
     }
+    encrypted_ = false;
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    maxwrappedsize_ = 0;
   }
   authenticationmechanisms_.Clear();
   supported_methods_.Clear();
@@ -4266,6 +4279,38 @@ bool BitToUserHandshake::MergePartialFromCodedStream(
           goto handle_uninterpreted;
         }
         if (input->ExpectTag(64)) goto parse_supported_methods;
+        if (input->ExpectTag(72)) goto parse_encrypted;
+        break;
+      }
+
+      // optional bool encrypted = 9;
+      case 9: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_encrypted:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &encrypted_)));
+          set_has_encrypted();
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(80)) goto parse_maxWrappedSize;
+        break;
+      }
+
+      // optional int32 maxWrappedSize = 10;
+      case 10: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+         parse_maxWrappedSize:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &maxwrappedsize_)));
+          set_has_maxwrappedsize();
+        } else {
+          goto handle_uninterpreted;
+        }
         if (input->ExpectAtEnd()) return true;
         break;
       }
@@ -4338,6 +4383,16 @@ void BitToUserHandshake::SerializeWithCachedSizes(
       8, this->supported_methods(i), output);
   }
 
+  // optional bool encrypted = 9;
+  if (has_encrypted()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(9, this->encrypted(), output);
+  }
+
+  // optional int32 maxWrappedSize = 10;
+  if (has_maxwrappedsize()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(10, this->maxwrappedsize(), output);
+  }
+
   if (!unknown_fields().empty()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
         unknown_fields(), output);
@@ -4399,6 +4454,16 @@ void BitToUserHandshake::SerializeWithCachedSizes(
       8, this->supported_methods(i), target);
   }
 
+  // optional bool encrypted = 9;
+  if (has_encrypted()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(9, this->encrypted(), target);
+  }
+
+  // optional int32 maxWrappedSize = 10;
+  if (has_maxwrappedsize()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(10, this->maxwrappedsize(), target);
+  }
+
   if (!unknown_fields().empty()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
         unknown_fields(), target);
@@ -4444,6 +4509,20 @@ int BitToUserHandshake::ByteSize() const {
           this->server_infos());
     }
 
+    // optional bool encrypted = 9;
+    if (has_encrypted()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // optional int32 maxWrappedSize = 10;
+    if (has_maxwrappedsize()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+          this->maxwrappedsize());
+    }
+
   }
   // repeated string authenticationMechanisms = 7;
   total_size += 1 * this->authenticationmechanisms_size();
@@ -4505,6 +4584,14 @@ void BitToUserHandshake::MergeFrom(const BitToUserHandshake& from) {
     if (from.has_server_infos()) {
       mutable_server_infos()->::exec::user::RpcEndpointInfos::MergeFrom(from.server_infos());
     }
+    if (from.has_encrypted()) {
+      set_encrypted(from.encrypted());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from.has_maxwrappedsize()) {
+      set_maxwrappedsize(from.maxwrappedsize());
+    }
   }
   mutable_unknown_fields()->MergeFrom(from.unknown_fields());
 }
@@ -4535,6 +4622,8 @@ void BitToUserHandshake::Swap(BitToUserHandshake* other) {
     std::swap(server_infos_, other->server_infos_);
     authenticationmechanisms_.Swap(&other->authenticationmechanisms_);
     supported_methods_.Swap(&other->supported_methods_);
+    std::swap(encrypted_, other->encrypted_);
+    std::swap(maxwrappedsize_, other->maxwrappedsize_);
     std::swap(_has_bits_[0], other->_has_bits_[0]);
     _unknown_fields_.Swap(&other->_unknown_fields_);
     std::swap(_cached_size_, other->_cached_size_);

http://git-wip-us.apache.org/repos/asf/drill/blob/d11aba2e/contrib/native/client/src/protobuf/User.pb.h
----------------------------------------------------------------------
diff --git a/contrib/native/client/src/protobuf/User.pb.h b/contrib/native/client/src/protobuf/User.pb.h
index a8f8db4..b50e8c3 100644
--- a/contrib/native/client/src/protobuf/User.pb.h
+++ b/contrib/native/client/src/protobuf/User.pb.h
@@ -117,11 +117,12 @@ inline bool RpcType_Parse(
 }
 enum SaslSupport {
   UNKNOWN_SASL_SUPPORT = 0,
-  SASL_AUTH = 1
+  SASL_AUTH = 1,
+  SASL_PRIVACY = 2
 };
 bool SaslSupport_IsValid(int value);
 const SaslSupport SaslSupport_MIN = UNKNOWN_SASL_SUPPORT;
-const SaslSupport SaslSupport_MAX = SASL_AUTH;
+const SaslSupport SaslSupport_MAX = SASL_PRIVACY;
 const int SaslSupport_ARRAYSIZE = SaslSupport_MAX + 1;
 
 const ::google::protobuf::EnumDescriptor* SaslSupport_descriptor();
@@ -1439,6 +1440,20 @@ class BitToUserHandshake : public ::google::protobuf::Message {
   inline const ::google::protobuf::RepeatedField<int>& supported_methods() const;
   inline ::google::protobuf::RepeatedField<int>* mutable_supported_methods();
 
+  // optional bool encrypted = 9;
+  inline bool has_encrypted() const;
+  inline void clear_encrypted();
+  static const int kEncryptedFieldNumber = 9;
+  inline bool encrypted() const;
+  inline void set_encrypted(bool value);
+
+  // optional int32 maxWrappedSize = 10;
+  inline bool has_maxwrappedsize() const;
+  inline void clear_maxwrappedsize();
+  static const int kMaxWrappedSizeFieldNumber = 10;
+  inline ::google::protobuf::int32 maxwrappedsize() const;
+  inline void set_maxwrappedsize(::google::protobuf::int32 value);
+
   // @@protoc_insertion_point(class_scope:exec.user.BitToUserHandshake)
  private:
   inline void set_has_rpc_version();
@@ -1451,6 +1466,10 @@ class BitToUserHandshake : public ::google::protobuf::Message {
   inline void clear_has_errormessage();
   inline void set_has_server_infos();
   inline void clear_has_server_infos();
+  inline void set_has_encrypted();
+  inline void clear_has_encrypted();
+  inline void set_has_maxwrappedsize();
+  inline void clear_has_maxwrappedsize();
 
   ::google::protobuf::UnknownFieldSet _unknown_fields_;
 
@@ -1461,9 +1480,11 @@ class BitToUserHandshake : public ::google::protobuf::Message {
   ::exec::user::RpcEndpointInfos* server_infos_;
   ::google::protobuf::RepeatedPtrField< ::std::string> authenticationmechanisms_;
   ::google::protobuf::RepeatedField<int> supported_methods_;
+  bool encrypted_;
+  ::google::protobuf::int32 maxwrappedsize_;
 
   mutable int _cached_size_;
-  ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+  ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
 
   friend void  protobuf_AddDesc_User_2eproto();
   friend void protobuf_AssignDesc_User_2eproto();
@@ -6226,6 +6247,50 @@ BitToUserHandshake::mutable_supported_methods() {
   return &supported_methods_;
 }
 
+// optional bool encrypted = 9;
+inline bool BitToUserHandshake::has_encrypted() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void BitToUserHandshake::set_has_encrypted() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void BitToUserHandshake::clear_has_encrypted() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+inline void BitToUserHandshake::clear_encrypted() {
+  encrypted_ = false;
+  clear_has_encrypted();
+}
+inline bool BitToUserHandshake::encrypted() const {
+  return encrypted_;
+}
+inline void BitToUserHandshake::set_encrypted(bool value) {
+  set_has_encrypted();
+  encrypted_ = value;
+}
+
+// optional int32 maxWrappedSize = 10;
+inline bool BitToUserHandshake::has_maxwrappedsize() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void BitToUserHandshake::set_has_maxwrappedsize() {
+  _has_bits_[0] |= 0x00000100u;
+}
+inline void BitToUserHandshake::clear_has_maxwrappedsize() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+inline void BitToUserHandshake::clear_maxwrappedsize() {
+  maxwrappedsize_ = 0;
+  clear_has_maxwrappedsize();
+}
+inline ::google::protobuf::int32 BitToUserHandshake::maxwrappedsize() const {
+  return maxwrappedsize_;
+}
+inline void BitToUserHandshake::set_maxwrappedsize(::google::protobuf::int32 value) {
+  set_has_maxwrappedsize();
+  maxwrappedsize_ = value;
+}
+
 // -------------------------------------------------------------------
 
 // LikeFilter