Skip to content

Commit

Permalink
One file to store all the certificate related function
Browse files Browse the repository at this point in the history
Signed-off-by: piyushawasthi <[email protected]>
  • Loading branch information
piyushawasthi committed Aug 28, 2017
1 parent 08c0cf4 commit deea2dc
Show file tree
Hide file tree
Showing 18 changed files with 427 additions and 126 deletions.
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
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ rvm:
branches:
only:
- master
before_install: gem install bundler -v 1.12.5
before_install:
- gem install bundler
script: bundle exec rake spec
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ source 'https://rubygems.org'

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

gem 'rb-readline', '~> 0.5.3'
gem 'pry'
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 "store/crypto"
require "certstore/certstore"
require "win32-certstore/version"
require 'certstore/certificate/certificate'
43 changes: 0 additions & 43 deletions lib/win32/api/reserved_names.rb

This file was deleted.

48 changes: 48 additions & 0 deletions lib/win32/certstore/certificate/cert_base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#
# 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/store/crypto'

module Win32
class Certstore
class Certificate
module CertBase
include Win32::Store::Crypto
include Chef::Mixin::ShellOut
include Chef::Mixin::WideString

def list_cert(store_handle)
cert_name = FFI::MemoryPointer.new(2, 128)
cert_list = []
begin
while (pCertContext = CertEnumCertificatesInStore(store_handle, pCertContext) and not pCertContext.null? ) do
if (CertGetNameStringW(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, 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
34 changes: 34 additions & 0 deletions lib/win32/certstore/certificate/certificate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#
# 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/cert_base'

module Win32
class Certstore
class Certificate
include Certificate::CertBase

# To Display Certificate List
# Take input certificate store name
# Return List in JSON format
def list(store_handler)
# Get Certificate list of open certificate store
return list_cert(store_handler)
end
end
end
end
33 changes: 26 additions & 7 deletions lib/win32/certstore/certstore.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.

require "win32/certstore/version"
require 'win32/api/reserved_names'
require 'win32/store/assertions'
require 'win32/store/crypto'

module Win32
module Certstore
include Win32::API::ReservedNames
include Chef::Mixin::WideString
class Certstore
extend Win32::Store::Assertions
extend Win32::Store::Crypto
extend Chef::Mixin::ShellOut
extend Chef::Mixin::WideString

def open store_name
def self.open(store_name)
certstore_handle = CertOpenSystemStoreW(nil, wstring(store_name))
unless certstore_handle
last_error = FFI::LastError.error
Expand All @@ -32,13 +34,30 @@ def open store_name
certstore_handle
end

def close certstore_handle
def self.close(certstore_handle)
include Win32::Store::Crypto
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

# CA -> Certification authority certificates.
# MY -> A certificate store that holds certificates with associated private keys.
# ROOT -> Root certificates.
# SPC -> Software Publisher Certificate.

def self.list_cert(certstore_name)
# TO verify Valid ceritificate store name
validate_store(certstore_name)
# Open Valid certificate store
store_handle = open(certstore_name)
list = Win32::Certstore::Certificate.new.list(store_handle)
# Close Open store
close(store_handle)
return list
end
end
end
5 changes: 0 additions & 5 deletions lib/win32/certstore/version.rb

This file was deleted.

37 changes: 37 additions & 0 deletions lib/win32/store/assertions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# 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::Store::Assertions

# Validate certificate store name
def validate_store(store_name)
unless valid_store_name.include?(store_name&.upcase)
raise ArgumentError, "Invalid Certificate Store."
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
99 changes: 99 additions & 0 deletions lib/win32/store/crypto.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#
# 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 Store
module Crypto
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)

# Certificate Display Format
CERT_NAME_EMAIL_TYPE = 1
CERT_NAME_RDN_TYPE = 2
CERT_NAME_ATTR_TYPE = 3
CERT_NAME_SIMPLE_DISPLAY_TYPE = 4
CERT_NAME_FRIENDLY_DISPLAY_TYPE = 5
CERT_NAME_DNS_TYPE = 6
CERT_NAME_URL_TYPE = 7
CERT_NAME_UPN_TYPE = 8

# List Certificates Flag
CERT_NAME_ISSUER_FLAG = 0x1
CERT_NAME_DISABLE_IE4_UTF8_FLAG = 0x00010000
CERT_NAME_SEARCH_ALL_NAMES_FLAG = 0x2
CERT_NAME_STR_ENABLE_PUNYCODE_FLAG = 0x00200000

# 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
6 changes: 6 additions & 0 deletions lib/win32/win32-certstore/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Win32
module Win32Certstore
VERSION = "1.0.0"
MAJOR, MINOR, TINY = VERSION.split('.')
end
end
6 changes: 3 additions & 3 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'win32/certstore/certstore'
require 'win32/certstore/certificate'
$LOAD_PATH.unshift File.expand_path('../../lib/win32', __FILE__)

require 'win32-certstore'
Loading

0 comments on commit deea2dc

Please sign in to comment.