List Info

Thread: RubyGems 0.9.0 Signing Updates




RubyGems 0.9.0 Signing Updates
user name
2006-08-31 07:44:11
Hi All,

Attached is a small patch against RubyGems 0.9.0 which adds
the
following:

  * Ensures that the trust directory exists and is a
directory
    before trying to add a certificate to the trust store.
  * Ensures that permissions on the trust directory and
generated
    certificates and keys are sufficiently restrictive.

On the off-chance that this patch gets mangled in transit,
it's also
available on the web at the following URL:

  http://pablotron.org/files/rubygems-0.9.0-signing_
updates.diff

For the security-conscious among you, an OpenPGP signature
of the
aforementioned patch can be found here:

  http://pablotron.org/files/rubygems-0.9.0-sign
ing_updates.diff.asc

It's a relatively small set of changes. That said,
questions, comments,
and unadulterated vitriol are always appreciated. 

-- 
Paul Duncan <pabspablotron.org>        OpenPGP Key ID:
0x82C29562
http://www.pablotron.org/               http://www.paulduncan.org/

diff -ur rubygems-0.9.0/lib/rubygems/security.rb
rubygems-0.9.0-fix_add_cert/lib/rubygems/security.rb
--- rubygems-0.9.0/lib/rubygems/security.rb	2006-06-06
23:39:54.000000000 -0400
+++
rubygems-0.9.0-fix_add_cert/lib/rubygems/security.rb	2006-08
-31 03:17:32.000000000 -0400
 -95,6
+95,14 
 
       # output directory for trusted certificate checksums
       :trust_dir => File::join(Gem.user_home, '.gem',
'trust'),
+
+      # default permissions for trust directory and certs
+      :perms => {
+        :trust_dir      => 0700,
+        :trusted_cert   => 0600,
+        :signing_cert   => 0600,
+        :signing_key    => 0600,
+      },
     }
 
     #
 -342,6
+350,32 
     end
     
     #
+    # Make sure the trust directory exists.  If it does
exist, make sure
+    # it's actually a directory.  If not, then create it
with the
+    # appropriate permissions.
+    #
+    def self.verify_trust_dir(opt)
+      # grab path from options
+      path = opt[:trust_dir]
+
+      # if the directory exists, then make sure it is in
fact a
+      # directory.  if it doesn't exist, then create it
with the
+      # appropriate permissions
+      if File.exists?(path)
+        # verify that the trust directory is actually a
directory
+        unless File.directory?(path)
+          err = "trust directory # isn't a
directory"
+          raise Gem::Security::Exception, err
+        end
+      else
+        # trust directory doesn't exist, so create it with

+        # permissions
+        FileUtils.mkdir_p(path)
+        FileUtils.chmod(opt[:perms][:trust_dir], path)
+      end
+    end
+
+    #
     # Build a certificate from the given DN and private
key.
     # 
     def self.build_cert(name, key, opt = {})
 -394,13
+428,16 
       # build private key
       key = opt[:key_algo].new(opt[:key_size])
 
-      # create the trust directory if it doesn't exist
-      FileUtils::mkdir_p(opt[:trust_dir]) unless
File.exists?(opt[:trust_dir])
+      # method name pretty much says it all 
+      verify_trust_dir(opt)
 
       # if we're saving the key, then write it out
       if opt[:save_key]
         path[:key] = opt[:save_key_path] ||
(opt[:output_fmt] % 'private_key')
-        File.open(path[:key], 'wb') { |file|
file.write(key.to_pem) }
+        File.open(path[:key], 'wb') do |file| 
+          file.chmod(opt[:perms][:signing_key])
+          file.write(key.to_pem) 
+        end
       end
       
       # build self-signed public cert from key
 -409,7
+446,10 
       # if we're saving the cert, then write it out
       if opt[:save_cert]
         path[:cert] = opt[:save_cert_path] ||
(opt[:output_fmt] % 'public_cert')
-        File.open(path[:cert], 'wb') { |file|
file.write(cert.to_pem) }
+        File.open(path[:cert], 'wb') do |file| 
+          file.chmod(opt[:perms][:signing_cert])
+          file.write(cert.to_pem)
+        end
       end
 
       # return key, cert, and paths (if applicable)
 -429,8
+469,14 
       # get destination path 
       path = Gem::Security::Policy.trusted_cert_path(cert,
opt)
 
+      # verify trust directory (can't write to nowhere,
you know)
+      verify_trust_dir(opt)
+
       # write cert to output file
-      File.open(path, 'wb') { |file|
file.write(cert.to_pem) }
+      File.open(path, 'wb') do |file| 
+        file.chmod(opt[:perms][:trusted_cert])
+        file.write(cert.to_pem)
+      end
 
       # return nil
       nil
_______________________________________________
Rubygems-developers mailing list
Rubygems-developersrubyforge.org
http://rubyforge.org/mailman/listinfo/rubygems-develope
rs
RubyGems 0.9.0 Signing Updates
user name
2006-08-31 17:42:50
On Aug 31, 2006, at 12:44 AM, Paul Duncan wrote:

> Hi All,
>
> Attached is a small patch against RubyGems 0.9.0 which
adds the
> following:
>
>   * Ensures that the trust directory exists and is a
directory
>     before trying to add a certificate to the trust
store.
>   * Ensures that permissions on the trust directory and
generated
>     certificates and keys are sufficiently restrictive.
>
> On the off-chance that this patch gets mangled in
transit, it's also
> available on the web at the following URL:
>
>   http://pablotron.org/files/rubygems-0.9.0-signing_
updates.diff
>
> For the security-conscious among you, an OpenPGP
signature of the
> aforementioned patch can be found here:
>
>   http://pablotron.org/files/rubygems-0.9.0-sign
ing_updates.diff.asc
>
> It's a relatively small set of changes. That said,
questions,  
> comments,
> and unadulterated vitriol are always appreciated. 
>
> diff -ur rubygems-0.9.0/lib/rubygems/security.rb
rubygems-0.9.0- 
> fix_add_cert/lib/rubygems/security.rb
> --- rubygems-0.9.0/lib/rubygems/security.rb	2006-06-06 

> 23:39:54.000000000 -0400
> +++
rubygems-0.9.0-fix_add_cert/lib/rubygems/security.rb	2006-08
-31  
> 03:17:32.000000000 -0400
>  -342,6 +350,32 
>      end
>
>      #
> +    # Make sure the trust directory exists.  If it
does exist,  
> make sure
> +    # it's actually a directory.  If not, then create
it with the
> +    # appropriate permissions.
> +    #
> +    def self.verify_trust_dir(opt)
> +      # grab path from options
> +      path = opt[:trust_dir]

opt[:trust_dir]

> +
> +      # if the directory exists, then make sure it is
in fact a
> +      # directory.  if it doesn't exist, then create
it with the
> +      # appropriate permissions
> +      if File.exists?(path)

File.exists? is deprecated, use File.exist.

> +        # verify that the trust directory is actually
a directory
> +        unless File.directory?(path)
> +          err = "trust directory # isn't
a directory"
> +          raise Gem::Security::Exception, err
> +        end
> +      else
> +        # trust directory doesn't exist, so create it
with
> +        # permissions
> +        FileUtils.mkdir_p(path)
> +        FileUtils.chmod(opt[:perms][:trust_dir], path)

and opt[:perms][:trust_dir] are the only things in opt you
use here,  
why not make them explicit arguments?

> +      end
> +    end
> +
> +    #
>      # Build a certificate from the given DN and
private key.
>      #
>      def self.build_cert(name, key, opt = {})
>  -429,8 +469,14 
>        # get destination path
>        path =
Gem::Security::Policy.trusted_cert_path(cert, opt)
>
> +      # verify trust directory (can't write to
nowhere, you know)
> +      verify_trust_dir(opt)
> +
>        # write cert to output file
> -      File.open(path, 'wb') { |file|
file.write(cert.to_pem) }
> +      File.open(path, 'wb') do |file|
> +        file.chmod(opt[:perms][:trusted_cert])
> +        file.write(cert.to_pem)
> +      end
>
>        # return nil
>        nil


-- 
Eric Hodel - drbrainsegment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotco
op.com


_______________________________________________
Rubygems-developers mailing list
Rubygems-developersrubyforge.org
http://rubyforge.org/mailman/listinfo/rubygems-develope
rs
RubyGems 0.9.0 Signing Updates
user name
2006-08-31 19:19:03
* Eric Hodel (drbrainsegment7.net) wrote:
[snipped]
> File.exists? is deprecated, use File.exist.

You sir, are correct.  

[snipped]
> and opt[:perms][:trust_dir] are the only things in opt
you use here,  
> why not make them explicit arguments?

I did it that way for consistency with the other calls. 
That said, I
see the advantage of the approach you're suggesting:
without a fancy
hash of options, the method is usable elsewhere.

I've updated the patch with both suggested changes.  The
new patch is
attached.  It's also available online at the following
URLs:

  http://pablotron.org/files/rubygems-0.9.0-signin
g_updates-2.diff
  http://pablotron.org/files/rubygems-0.9.0-si
gning_updates-2.diff.asc

Thanks!

> -- 
> Eric Hodel - drbrainsegment7.net - http://blog.segment7.net
> This implementation is HODEL-HASH-9600 compliant

-- 
Paul Duncan <pabspablotron.org>        OpenPGP Key ID:
0x82C29562
http://www.pablotron.org/               http://www.paulduncan.org/

diff -ur rubygems-0.9.0/lib/rubygems/package.rb
rubygems-0.9.0-fix_add_cert/lib/rubygems/package.rb
--- rubygems-0.9.0/lib/rubygems/package.rb	2006-06-13
23:39:45.000000000 -0400
+++
rubygems-0.9.0-fix_add_cert/lib/rubygems/package.rb	2006-08-
31 14:58:01.000000000 -0400
 -525,7
+525,7 
             if
Gem::Security.constants.index(security_policy)
               # load one of the pre-defined security
policies
               security_policy =
Gem::Security.const_get(security_policy)
-            elsif File.exists?(security_policy)
+            elsif File.exist?(security_policy)
               # FIXME: this doesn't work yet
               security_policy =
YAML::load(File.read(security_policy))
             else
diff -ur rubygems-0.9.0/lib/rubygems/security.rb
rubygems-0.9.0-fix_add_cert/lib/rubygems/security.rb
--- rubygems-0.9.0/lib/rubygems/security.rb	2006-06-06
23:39:54.000000000 -0400
+++
rubygems-0.9.0-fix_add_cert/lib/rubygems/security.rb	2006-08
-31 14:57:37.000000000 -0400
 -95,6
+95,14 
 
       # output directory for trusted certificate checksums
       :trust_dir => File::join(Gem.user_home, '.gem',
'trust'),
+
+      # default permissions for trust directory and certs
+      :perms => {
+        :trust_dir      => 0700,
+        :trusted_cert   => 0600,
+        :signing_cert   => 0600,
+        :signing_key    => 0600,
+      },
     }
 
     #
 -216,7
+224,7 
                 'Untrusted Signing Chain Root',
                 root.subject.to_s,
                 "path \"#\" does
not exist",
-              ] unless File.exists?(path)
+              ] unless File.exist?(path)
 
               # load calculate digest from saved cert file
               save_cert =
OpenSSL::X509::Certificate.new(File.read(path))
 -342,6
+350,29 
     end
     
     #
+    # Make sure the trust directory exists.  If it does
exist, make sure
+    # it's actually a directory.  If not, then create it
with the
+    # appropriate permissions.
+    #
+    def self.verify_trust_dir(path, perms)
+      # if the directory exists, then make sure it is in
fact a
+      # directory.  if it doesn't exist, then create it
with the
+      # appropriate permissions
+      if File.exist?(path)
+        # verify that the trust directory is actually a
directory
+        unless File.directory?(path)
+          err = "trust directory # isn't a
directory"
+          raise Gem::Security::Exception, err
+        end
+      else
+        # trust directory doesn't exist, so create it with

+        # permissions
+        FileUtils.mkdir_p(path)
+        FileUtils.chmod(perms, path)
+      end
+    end
+
+    #
     # Build a certificate from the given DN and private
key.
     # 
     def self.build_cert(name, key, opt = {})
 -394,13
+425,16 
       # build private key
       key = opt[:key_algo].new(opt[:key_size])
 
-      # create the trust directory if it doesn't exist
-      FileUtils::mkdir_p(opt[:trust_dir]) unless
File.exists?(opt[:trust_dir])
+      # method name pretty much says it all 
+      verify_trust_dir(opt[:trust_dir],
opt[:perms][:trust_dir])
 
       # if we're saving the key, then write it out
       if opt[:save_key]
         path[:key] = opt[:save_key_path] ||
(opt[:output_fmt] % 'private_key')
-        File.open(path[:key], 'wb') { |file|
file.write(key.to_pem) }
+        File.open(path[:key], 'wb') do |file| 
+          file.chmod(opt[:perms][:signing_key])
+          file.write(key.to_pem) 
+        end
       end
       
       # build self-signed public cert from key
 -409,7
+443,10 
       # if we're saving the cert, then write it out
       if opt[:save_cert]
         path[:cert] = opt[:save_cert_path] ||
(opt[:output_fmt] % 'public_cert')
-        File.open(path[:cert], 'wb') { |file|
file.write(cert.to_pem) }
+        File.open(path[:cert], 'wb') do |file| 
+          file.chmod(opt[:perms][:signing_cert])
+          file.write(cert.to_pem)
+        end
       end
 
       # return key, cert, and paths (if applicable)
 -429,8
+466,14 
       # get destination path 
       path = Gem::Security::Policy.trusted_cert_path(cert,
opt)
 
+      # verify trust directory (can't write to nowhere,
you know)
+      verify_trust_dir(opt[:trust_dir],
opt[:perms][:trust_dir])
+
       # write cert to output file
-      File.open(path, 'wb') { |file|
file.write(cert.to_pem) }
+      File.open(path, 'wb') do |file| 
+        file.chmod(opt[:perms][:trusted_cert])
+        file.write(cert.to_pem)
+      end
 
       # return nil
       nil
 -460,7
+503,7 
             # convert it into a cert object, and if it's a
cert object,
             # leave it alone
             if cert &&
!cert.kind_of?(OpenSSL::X509::Certificate)
-              cert = File.read(cert) if File::exists?(cert)
+              cert = File.read(cert) if File::exist?(cert)
               cert = OpenSSL::X509::Certificate.new(cert)
             end
             cert
_______________________________________________
Rubygems-developers mailing list
Rubygems-developersrubyforge.org
http://rubyforge.org/mailman/listinfo/rubygems-develope
rs
[1-3]

about | contact  Other archives ( Real Estate discussion Medical topics )