mirror of
https://github.com/rest-client/rest-client.git
synced 2022-11-09 13:49:40 -05:00
Adapt Windows root cert store code from puppet.
This commit is contained in:
parent
e30ecc8929
commit
1d0f0d9fa3
4 changed files with 121 additions and 0 deletions
2
Gemfile
2
Gemfile
|
|
@ -2,6 +2,8 @@ source "https://rubygems.org"
|
|||
|
||||
gemspec
|
||||
|
||||
gem 'ffi', '~> 1.9', :platforms => [:mswin, :mingw]
|
||||
|
||||
group :test do
|
||||
gem 'rake'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ require File.dirname(__FILE__) + '/restclient/raw_response'
|
|||
require File.dirname(__FILE__) + '/restclient/resource'
|
||||
require File.dirname(__FILE__) + '/restclient/payload'
|
||||
require File.dirname(__FILE__) + '/restclient/net_http_ext'
|
||||
require File.dirname(__FILE__) + '/restclient/windows'
|
||||
|
||||
# This module's static methods are the entry point for using the REST client.
|
||||
#
|
||||
|
|
|
|||
13
lib/restclient/windows.rb
Normal file
13
lib/restclient/windows.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
module RestClient
|
||||
module Windows
|
||||
def self.windows?
|
||||
# Ruby only sets File::ALT_SEPARATOR on Windows, and the Ruby standard
|
||||
# library uses that to test what platform it's on.
|
||||
!!File::ALT_SEPARATOR
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if RestClient::Windows.windows?
|
||||
require_relative './windows/root_certs'
|
||||
end
|
||||
105
lib/restclient/windows/root_certs.rb
Normal file
105
lib/restclient/windows/root_certs.rb
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
require 'openssl'
|
||||
require 'ffi'
|
||||
|
||||
# Adapted from Puppet, Copyright (c) Puppet Labs Inc,
|
||||
# licensed under the Apache License, Version 2.0.
|
||||
#
|
||||
# https://github.com/puppetlabs/puppet/blob/bbe30e0a/lib/puppet/util/windows/root_certs.rb
|
||||
|
||||
# Represents a collection of trusted root certificates.
|
||||
#
|
||||
# @api public
|
||||
class RestClient::Windows::RootCerts
|
||||
include Enumerable
|
||||
extend FFI::Library
|
||||
|
||||
typedef :ulong, :dword
|
||||
typedef :uintptr_t, :handle
|
||||
|
||||
def initialize(roots)
|
||||
@roots = roots
|
||||
end
|
||||
|
||||
# Enumerates each root certificate.
|
||||
# @yieldparam cert [OpenSSL::X509::Certificate] each root certificate
|
||||
# @api public
|
||||
def each
|
||||
@roots.each {|cert| yield cert}
|
||||
end
|
||||
|
||||
# Returns a new instance.
|
||||
# @return [Puppet::Util::Windows::RootCerts] object constructed from current root certificates
|
||||
def self.instance
|
||||
new(self.load_certs)
|
||||
end
|
||||
|
||||
# Returns an array of root certificates.
|
||||
#
|
||||
# @return [Array<[OpenSSL::X509::Certificate]>] an array of root certificates
|
||||
# @api private
|
||||
def self.load_certs
|
||||
certs = []
|
||||
|
||||
# This is based on a patch submitted to openssl:
|
||||
# http://www.mail-archive.com/openssl-dev@openssl.org/msg26958.html
|
||||
ptr = FFI::Pointer::NULL
|
||||
store = CertOpenSystemStoreA(nil, "ROOT")
|
||||
begin
|
||||
while (ptr = CertEnumCertificatesInStore(store, ptr)) and not ptr.null?
|
||||
context = CERT_CONTEXT.new(ptr)
|
||||
cert_buf = context[:pbCertEncoded].read_bytes(context[:cbCertEncoded])
|
||||
begin
|
||||
certs << OpenSSL::X509::Certificate.new(cert_buf)
|
||||
rescue => detail
|
||||
Puppet.warning("Failed to import root certificate: #{detail.inspect}")
|
||||
end
|
||||
end
|
||||
ensure
|
||||
CertCloseStore(store, 0)
|
||||
end
|
||||
|
||||
certs
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# typedef ULONG_PTR HCRYPTPROV_LEGACY;
|
||||
# typedef void *HCERTSTORE;
|
||||
|
||||
class CERT_CONTEXT < FFI::Struct
|
||||
layout(
|
||||
:dwCertEncodingType, :dword,
|
||||
:pbCertEncoded, :pointer,
|
||||
:cbCertEncoded, :dword,
|
||||
:pCertInfo, :pointer,
|
||||
:hCertStore, :handle
|
||||
)
|
||||
end
|
||||
|
||||
# HCERTSTORE
|
||||
# WINAPI
|
||||
# CertOpenSystemStoreA(
|
||||
# __in_opt HCRYPTPROV_LEGACY hProv,
|
||||
# __in LPCSTR szSubsystemProtocol
|
||||
# );
|
||||
ffi_lib :crypt32
|
||||
attach_function :CertOpenSystemStoreA, [:pointer, :string], :handle
|
||||
|
||||
# PCCERT_CONTEXT
|
||||
# WINAPI
|
||||
# CertEnumCertificatesInStore(
|
||||
# __in HCERTSTORE hCertStore,
|
||||
# __in_opt PCCERT_CONTEXT pPrevCertContext
|
||||
# );
|
||||
ffi_lib :crypt32
|
||||
attach_function :CertEnumCertificatesInStore, [:handle, :pointer], :pointer
|
||||
|
||||
# BOOL
|
||||
# WINAPI
|
||||
# CertCloseStore(
|
||||
# __in_opt HCERTSTORE hCertStore,
|
||||
# __in DWORD dwFlags
|
||||
# );
|
||||
ffi_lib :crypt32
|
||||
attach_function :CertCloseStore, [:handle, :dword], :bool
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue