From 0be24225890a19060bae5edf103aa94442cef4e7 Mon Sep 17 00:00:00 2001
From: mohamedhafez <mohamed.m.m.hafez@gmail.com>
Date: Mon, 26 Sep 2011 20:39:12 -0700
Subject: [PATCH 1/3] Allows the optional declaration of a whitelist of
 methods to expose through DRb for any class DRb will be
 sharing an instance of. (The current behavior of
 exposing all public methods of a class can leave a
 pretty scary security hole in some applications)

If drb_safe_methods is used in a class's definition, then any attempt to call a non-whitelisted method on that class through DRb will fail. There is no change to DRb's normal behavior if drb_safe_methods has not been called in a class's definition.
---
 lib/drb/drb.rb |   31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
index 69456b1..588e421 100644
--- a/lib/drb/drb.rb
+++ b/lib/drb/drb.rb
@@ -1437,8 +1437,12 @@ def run
     ]
 
     # Has a method been included in the list of insecure methods?
+    # Or, if a list of drb-safe methods has been defined for the
+    # front object, is this method not included in that list?
     def insecure_method?(msg_id)
-      INSECURE_METHOD.include?(msg_id)
+      INSECURE_METHOD.include?(msg_id) ||
+        (@front.respond_to?(:drb_safe_methods_list) &&
+         !@front.drb_safe_methods_list.include?(msg_id))
     end
 
     # Coerce an object to a string, providing our own representation if
@@ -1768,6 +1772,31 @@ def fetch_server(uri)
   module_function :fetch_server
 end
 
+
+# Declare a list of methods to expose to DRb
+#
+# Allows the optional declaration of a whitelist of methods to expose
+# through DRb for any class DRb will be sharing an instance of. If
+# drb_safe_methods is used, then any attempt to call a non-whitelisted
+# method on that class through DRb will fail.
+#
+# EXAMPLE USAGE:
+# def MyClass
+#   drb_safe_methods :method1, :method2
+# end
+#
+# NOTE: if you are using irb as the client and :to_s isn't in the list,
+# you will get a DRb::DRbConnError when you create the DRbObject, but only
+# because irb calls to_s to display the result; the DRbObject is still
+# usable.
+class Class
+  def drb_safe_methods(*symbols)
+    define_method(:drb_safe_methods_list) do
+      symbols
+    end
+  end
+end
+
 # :stopdoc:
 DRbObject = DRb::DRbObject
 DRbUndumped = DRb::DRbUndumped
-- 
1.7.10


From 704c7a6fc13bd65415d3bfa259765d2f1ead1625 Mon Sep 17 00:00:00 2001
From: mohamedhafez <mohamed.m.m.hafez@gmail.com>
Date: Wed, 28 Sep 2011 21:05:27 -0700
Subject: [PATCH 2/3] whoops, I was checking @front each time for the
 drb_safe_methods_list, in order to deal correctly for
 DRbUndumped objects i needed to pass it the actual obj
 from check_insecure_method and check that instead

---
 lib/drb/drb.rb |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
index 588e421..785d85d 100644
--- a/lib/drb/drb.rb
+++ b/lib/drb/drb.rb
@@ -1439,12 +1439,13 @@ def run
     # Has a method been included in the list of insecure methods?
     # Or, if a list of drb-safe methods has been defined for the
     # front object, is this method not included in that list?
-    def insecure_method?(msg_id)
+    def insecure_method?(obj, msg_id)
       INSECURE_METHOD.include?(msg_id) ||
-        (@front.respond_to?(:drb_safe_methods_list) &&
-         !@front.drb_safe_methods_list.include?(msg_id))
+        (obj.respond_to?(:drb_safe_methods_list) &&
+         !obj.drb_safe_methods_list.include?(msg_id))
     end
 
+
     # Coerce an object to a string, providing our own representation if
     # to_s is not defined for the object.
     def any_to_s(obj)
@@ -1464,7 +1465,7 @@ def any_to_s(obj)
     def check_insecure_method(obj, msg_id)
       return true if Proc === obj && msg_id == :__drb_yield
       raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class
-      raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id)
+      raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(obj, msg_id)
 
       if obj.private_methods.include?(msg_id)
         desc = any_to_s(obj)
-- 
1.7.10


From 96665e3b27595c338f6b9855a112259117098bd8 Mon Sep 17 00:00:00 2001
From: mohamedhafez <mohamed.m.m.hafez@gmail.com>
Date: Wed, 19 Oct 2011 10:49:42 -0700
Subject: [PATCH 3/3] I was accidentally classifying private methods,
 protected methods,and unimplemented methods as insecure
 methods. this commit fixes that

---
 lib/drb/drb.rb |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
index 785d85d..c56bfe5 100644
--- a/lib/drb/drb.rb
+++ b/lib/drb/drb.rb
@@ -1441,7 +1441,8 @@ def run
     # front object, is this method not included in that list?
     def insecure_method?(obj, msg_id)
       INSECURE_METHOD.include?(msg_id) ||
-        (obj.respond_to?(:drb_safe_methods_list) &&
+        (obj.public_methods.include?(:drb_safe_methods_list)  &&
+         obj.public_methods.include?(msg_id) &&
          !obj.drb_safe_methods_list.include?(msg_id))
     end
 
-- 
1.7.10

