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-signing_updates.diff.asc
It's a relatively small set of changes. That said, questions, comments,
and unadulterated vitriol are always appreciated. :)
--
Paul Duncan <[EMAIL PROTECTED]> 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 #{path} 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
signature.asc
Description: Digital signature
_______________________________________________ Rubygems-developers mailing list [email protected] http://rubyforge.org/mailman/listinfo/rubygems-developers
