Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSYS-546 - List certificates of specific certificate store #3

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ build-iPhoneSimulator/

# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
Gemfile.lock
# .ruby-version
# .ruby-gemset

Expand Down
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ rvm:
branches:
only:
- master
before_install: gem install bundler -v 1.12.5
before_install:
- ./kill-travis.sh
- gem install bundler

script: bundle exec rake spec
11 changes: 7 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
source 'https://rubygems.org'

# Specify your gem's dependencies in win32-certstore.gemspec
gemspec
source 'https://rubygems.org'

# Specify your gem's dependencies in win32-certstore.gemspec
gemspec

gem 'pry'
gem 'rb-readline'
22 changes: 5 additions & 17 deletions lib/win32-certstore.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
#
# Author:: Nimisha Sharad (<[email protected]>)
# Copyright:: Copyright (c) 2017 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed 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.
$LOAD_PATH.unshift File.expand_path('../../lib/win32', __FILE__)

require 'win32/certstore/certstore'
require "backend/core_ext"
require "certstore/certstore"
require "win32-certstore/version"
require 'certstore/certificate/list'
43 changes: 0 additions & 43 deletions lib/win32/api/reserved_names.rb

This file was deleted.

83 changes: 83 additions & 0 deletions lib/win32/backend/core_ext.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#
# Author:: Nimisha Sharad (<[email protected]>)
# Copyright:: Copyright (c) 2017 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed 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.
#

require 'ffi'
require 'chef'
require 'chef/win32/api'
require 'mixlib/shellout'

module Win32
module Backend
module CoreExt
extend Chef::ReservedNames::Win32::API
extend FFI::Library

ffi_lib 'Crypt32'
ffi_convention :stdcall

###############################################
# Win32 API Constants
###############################################

CERT_CLOSE_STORE_CHECK_FLAG = 0
CERT_CLOSE_STORE_FORCE_FLAG = 1

# cert encoding flags.
CRYPT_ASN_ENCODING = 0x00000001
CRYPT_NDR_ENCODING = 0x00000002
X509_ASN_ENCODING = 0x00000001
X509_NDR_ENCODING = 0x00000002
PKCS_7_ASN_ENCODING = 0x00010000
PKCS_7_NDR_ENCODING = 0x00020000
PKCS_7_OR_X509_ASN_ENCODING = (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

# Define ffi pointer
HCERTSTORE = FFI::TypeDefs[:pointer]
HCRYPTPROV_LEGACY = FFI::TypeDefs[:pointer]
PCCERT_CONTEXT = FFI::TypeDefs[:pointer]
BYTE = FFI::TypeDefs[:pointer]

class CERT_CONTEXT < FFI::Struct
layout :hCertStore, :HANDLE,
:dwCertEncodingType, :DWORD,
:pbCertEncoded, :PWSTR,
:cbCertEncoded, :DWORD,
:pCertInfo, :pointer
end

###############################################################################
# Windows Function
# To know description about below windows function
# Search Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376560
###############################################################################

# To opens the most common system certificate store
safe_attach_function :CertOpenSystemStoreW, [HCRYPTPROV_LEGACY, :LPCTSTR], HCERTSTORE
# To close the already open certificate store
safe_attach_function :CertCloseStore, [HCERTSTORE, :DWORD], :BOOL
# To retrieves certificates in a certificate store
safe_attach_function :CertEnumCertificatesInStore, [HCERTSTORE, PCCERT_CONTEXT], PCCERT_CONTEXT
# To get certificate name
safe_attach_function :CertGetNameStringW, [PCCERT_CONTEXT, :DWORD, :DWORD, :LPVOID, :LPTSTR, :DWORD], :DWORD
# To find all of the property identifiers for the specified certificate.
safe_attach_function :CertEnumCertificateContextProperties, [PCCERT_CONTEXT, :DWORD], :DWORD
# Clean up
safe_attach_function :CertFreeCertificateContext, [PCCERT_CONTEXT], :BOOL
end
end
end
44 changes: 44 additions & 0 deletions lib/win32/backend/policies.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#
# Author:: Piyush Awasthi (<[email protected]>)
# Copyright:: Copyright (c) 2017 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed 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.

module Win32::Backend::Policies

# Validate import certificate file format
def validate_args(import_cert_params)
unless import_cert_params.each_index.select {|i| import_cert_params[i] =~ /.cer|.crt|.pfx|.der/}
raise ArgumentError, "Invalid Certificate format."
end
end

# Validate certificate store name
def validate_store(store_name)
unless valid_store_name.include?(store_name&.upcase)
raise ArgumentError, "Invalid Certificate Store Name."
end
end

private

# These Are Valid certificate store name
# CA -> Certification authority certificates.
# MY -> A certificate store that holds certificates with associated private keys.
# ROOT -> Root certificates.
# SPC -> Software Publisher Certificate.
def valid_store_name
["MY", "CA", "ROOT", "SPC"]
end
end
29 changes: 0 additions & 29 deletions lib/win32/certstore/certificate.rb

This file was deleted.

62 changes: 62 additions & 0 deletions lib/win32/certstore/certificate/list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#
# Author:: Piyush Awasthi (<[email protected]>)
# Copyright:: Copyright (c) 2017 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed 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.

require 'win32/certstore/certificate/win32_base'

module Win32
class Certstore
class Certificate
class List < Certificate
include Certificate::Win32Base

def initialize(store_name)
@store_name = store_name
# TO verify Valid ceritificate store name
validate_store(@store_name)
end

def show
# Open Valid certificate store
@store_handle = open_store(@store_name)
# Get Certificate list of open certificate store
certificates_list = list_cert
# Close Open store
close_store(@store_handle)
return certificates_list
end

def list_cert
cert_name = FFI::MemoryPointer.new(2, 128)
cert_list = []
begin
while (pCertContext = CertEnumCertificatesInStore(@store_handle, pCertContext) and not pCertContext.null? ) do
if (CertGetNameStringW(pCertContext, 5, 0, nil, cert_name, 1024))
cert_list << cert_name.read_wstring
end
end
CertFreeCertificateContext(pCertContext)
rescue Exception => e
last_error = FFI::LastError.error
raise Chef::Exceptions::Win32APIError, "Unable to load certificate with error: #{last_error}."
end
cert_list.to_json
end

end
end
end
end
69 changes: 69 additions & 0 deletions lib/win32/certstore/certificate/win32_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#
# Author:: Piyush Awasthi (<[email protected]>)
# Copyright:: Copyright (c) 2017 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed 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.

require 'win32/backend/core_ext'
require 'win32/backend/policies'

module Win32
class Certstore
class Certificate
module Win32Base
include Win32::Backend::CoreExt
include Win32::Backend::Policies
include Chef::Mixin::ShellOut
include Chef::Mixin::WideString

def open_store(store_name)
certstore_handle = CertOpenSystemStoreW(nil, wstring(store_name))
unless certstore_handle
last_error = FFI::LastError.error
raise Chef::Exceptions::Win32APIError, "Unable to open the Certificate Store `#{store_name}` with error: #{last_error}."
end
certstore_handle
end

def close_store(certstore_handle)
closed = CertCloseStore(certstore_handle, CERT_CLOSE_STORE_FORCE_FLAG)
unless closed
last_error = FFI::LastError.error
raise Chef::Exceptions::Win32APIError, "Unable to close the Certificate Store with error: #{last_error}."
end
closed
end

def update_params(user_parms)
if user_parms.size > 1
path_index = user_parms.each_index.select{|i| user_parms[i] =~ /.cer|.crt|.pfx|.der/}.first
user_parms[0], user_parms[user_parms.size-1] = user_parms.find{|loc| loc != user_parms[path_index]}.delete(' '), user_parms[path_index]
else
user_parms[0], user_parms[1] = "ROOT", user_parms[0]
end
end

def get_PScommand(user_parms)
user_parms = update_params(user_parms)
if user_parms.last =~ /.pfx/
cmd = "powershell.exe -Command certutil -addstore -f -importpfx '#{user_parms.first}' '#{user_parms.last}'"
else
cmd = "powershell.exe -Command certutil -addstore -f -v '#{user_parms.first}' '#{user_parms.last}'"
end
cmd
end
end
end
end
end
Loading