ios-cert-enrollment 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ require File.expand_path('../ios-cert-enrollment/configuration', __FILE__)
2
+ require File.expand_path('../ios-cert-enrollment/sign', __FILE__)
3
+ require File.expand_path('../ios-cert-enrollment/profile', __FILE__)
4
+ require File.expand_path('../ios-cert-enrollment/device', __FILE__)
5
+
6
+ module IOSCertEnrollment
7
+ extend Configuration
8
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../configuration', __FILE__)
2
+ require "openssl"
3
+
4
+ module IOSCertEnrollment
5
+ class Certificate
6
+
7
+ attr_accessor :certificate, :mime_type
8
+
9
+ def initialize(certificate,mime_type)
10
+ self.certificate = certificate
11
+ self.mime_type = mime_type
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../version', __FILE__)
2
+
3
+ module IOSCertEnrollment
4
+ # Defines constants and methods related to configuration
5
+ module Configuration
6
+ VALID_OPTIONS_KEYS = [
7
+ :ssl_certificate_path,
8
+ :ssl_key_path,
9
+ :base_url,
10
+ :identifier,
11
+ :display_name,
12
+ :organization
13
+ ].freeze
14
+
15
+ attr_accessor *VALID_OPTIONS_KEYS
16
+
17
+ # Convenience method to allow configuration options to be set in a block
18
+ def configure
19
+ yield self
20
+ end
21
+
22
+ # Create a hash of options and their values
23
+ def options
24
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
25
+ option.merge!(key => send(key))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path('../configuration', __FILE__)
2
+ require File.expand_path('../certificate', __FILE__)
3
+ require File.expand_path('../ssl', __FILE__)
4
+
5
+ require "plist"
6
+
7
+ module IOSCertEnrollment
8
+ module Device
9
+ class << self
10
+ def parse(p7sign)
11
+ return Plist::parse_xml(p7sign.data)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,153 @@
1
+ require File.expand_path('../configuration', __FILE__)
2
+ require "rubygems"
3
+ require "uuidtools"
4
+ require "plist"
5
+ module IOSCertEnrollment
6
+ class Profile
7
+ attr_accessor :url, :identifier, :display_name, :description, :icon, :payload, :organization, :expiration
8
+ def initialize(url="")
9
+ self.url = IOSCertEnrollment.base_url + url
10
+ self.identifier = IOSCertEnrollment.identifier
11
+ self.display_name = IOSCertEnrollment.display_name
12
+ self.organization = IOSCertEnrollment.organization
13
+ self.description = ""
14
+ self.expiration = nil
15
+
16
+ end
17
+
18
+ def service
19
+ payload = general_payload()
20
+ payload['PayloadType'] = "Profile Service" # do not modify
21
+ payload['PayloadIdentifier'] = self.identifier+".mobileconfig.profile-service"
22
+
23
+ # strings that show up in UI, customizable
24
+ payload['PayloadDisplayName'] = self.display_name
25
+ payload['PayloadDescription'] = self.description
26
+
27
+ payload_content = Hash.new
28
+ payload_content['URL'] = self.url
29
+ payload_content['DeviceAttributes'] = [
30
+ "UDID",
31
+ "VERSION",
32
+ "PRODUCT", # ie. iPhone1,1 or iPod2,1
33
+ "DEVICE_NAME", # given device name "My iPhone"
34
+ "MAC_ADDRESS_EN0",
35
+ "IMEI",
36
+ "ICCID"
37
+ ];
38
+
39
+ payload['PayloadContent'] = payload_content
40
+ self.payload = Plist::Emit.dump(payload)
41
+ return self
42
+ end
43
+
44
+ def encrypted_service
45
+ ## ASA encryption_cert_payload
46
+ payload = general_payload()
47
+
48
+ payload['PayloadIdentifier'] = self.identifier+".encrypted-profile-service"
49
+ payload['PayloadType'] = "Configuration" # do not modify
50
+
51
+ # strings that show up in UI, customisable
52
+ payload['PayloadDisplayName'] = self.display_name
53
+ payload['PayloadDescription'] = self.description
54
+
55
+ payload['PayloadContent'] = [encryption_cert_request("Profile Service")];
56
+ self.payload = Plist::Emit.dump(payload)
57
+ return self
58
+ end
59
+
60
+
61
+ def webclip
62
+
63
+ webclip_payload = general_payload()
64
+
65
+ webclip_payload['PayloadIdentifier'] = self.identifier+".webclip.tester"
66
+ webclip_payload['PayloadType'] = "com.apple.webClip.managed" # do not modify
67
+
68
+ # strings that show up in UI, customisable
69
+ webclip_payload['PayloadDisplayName'] = self.display_name
70
+ webclip_payload['PayloadDescription'] = self.description
71
+
72
+ # allow user to remove webclip
73
+ webclip_payload['IsRemovable'] = true
74
+ webclip_payload['FullScreen'] = true
75
+ webclip_payload['Icon'] = self.icon
76
+ webclip_payload['Precomposed'] = true
77
+ # the link
78
+ webclip_payload['Label'] = self.display_name
79
+ webclip_payload['URL'] = self.url
80
+
81
+ #client_cert_payload = scep_cert_payload(request, "Client Authentication", "foo");
82
+
83
+ self.payload = Plist::Emit.dump(payload)
84
+ return self
85
+
86
+ end
87
+
88
+
89
+
90
+ def configuration(encrypted_content)
91
+ payload = general_payload()
92
+ payload['PayloadIdentifier'] = self.identifier+".intranet"
93
+ payload['PayloadType'] = "Configuration" # do not modify
94
+
95
+ # strings that show up in UI, customisable
96
+ payload['PayloadDisplayName'] = self.display_name
97
+ payload['PayloadDescription'] = self.description
98
+ payload['PayloadExpirationDate'] = self.expiration || Date.today + (360 * 10) # expire in 10 years
99
+
100
+ payload['EncryptedPayloadContent'] = StringIO.new(encrypted_content)
101
+ self.payload = Plist::Emit.dump(payload)
102
+ return self
103
+
104
+ end
105
+
106
+ def sign
107
+ signed_profile = OpenSSL::PKCS7.sign(SSL.certificate, SSL.key, self.payload, [], OpenSSL::PKCS7::BINARY)
108
+ return Certificate.new(signed_profile.to_der, "application/x-apple-aspen-config")
109
+
110
+ end
111
+
112
+ def encrypt(certificates)
113
+ encrypted_profile = OpenSSL::PKCS7.encrypt(certificates, self.payload, OpenSSL::Cipher::Cipher::new("des-ede3-cbc"), OpenSSL::PKCS7::BINARY)
114
+ return Certificate.new(encrypted_profile.to_der, "application/x-apple-aspen-config")
115
+
116
+ end
117
+
118
+
119
+ private
120
+ def encryption_cert_request(purpose)
121
+ ## AKA scep_cert_payload
122
+ payload = general_payload()
123
+
124
+
125
+ payload['PayloadIdentifier'] = self.identifier+".encryption-cert-request"
126
+ payload['PayloadType'] = "com.apple.security.scep" # do not modify
127
+
128
+ payload['PayloadDisplayName'] = purpose
129
+ payload['PayloadDescription'] = "Provides device encryption identity"
130
+
131
+ payload_content = Hash.new
132
+ payload_content['URL'] = self.url
133
+ payload_content['Subject'] = [ [ [ "O", self.organization ] ],
134
+ [ [ "CN", purpose + " (" + UUIDTools::UUID.random_create().to_s + ")" ] ] ];
135
+
136
+ payload_content['Keysize'] = 1024
137
+ payload_content['Key Type'] = "RSA"
138
+ payload_content['Key Usage'] = 5 # digital signature (1) | key encipherment (4)
139
+ payload_content['GetCACaps'] = ["POSTPKIOperation","Renewal","SHA-1"]
140
+
141
+ payload['PayloadContent'] = payload_content;
142
+ payload
143
+ end
144
+
145
+ def general_payload()
146
+ payload = Hash.new
147
+ payload['PayloadVersion'] = 1 # do not modify
148
+ payload['PayloadUUID'] = UUIDTools::UUID.random_create().to_s # should be unique
149
+ payload['PayloadOrganization'] = self.organization
150
+ payload
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,85 @@
1
+ require File.expand_path('../configuration', __FILE__)
2
+ require File.expand_path('../certificate', __FILE__)
3
+ require File.expand_path('../ssl', __FILE__)
4
+
5
+ require "openssl"
6
+
7
+ module IOSCertEnrollment
8
+ module Sign
9
+
10
+ class << self
11
+ def registration_authority
12
+ scep_certs = OpenSSL::PKCS7.new()
13
+ scep_certs.type="signed"
14
+ scep_certs.certificates=[SSL.certificate,SSL.certificate]
15
+ return Certificate.new(scep_certs.to_der, "application/x-x509-ca-ra-cert")
16
+ end
17
+
18
+ def certificate_authority_caps
19
+ return "POSTPKIOperation\nSHA-1\nDES3\n"
20
+ end
21
+
22
+ def sign_PKI(data)
23
+
24
+ p7sign = OpenSSL::PKCS7.new(data)
25
+ store = OpenSSL::X509::Store.new
26
+ p7sign.verify(nil, store, nil, OpenSSL::PKCS7::NOVERIFY)
27
+ signers = p7sign.signers
28
+ p7enc = OpenSSL::PKCS7.new(p7sign.data)
29
+
30
+ # Certificate Signing Request
31
+ csr = p7enc.decrypt(SSL.key, SSL.certificate)
32
+
33
+ # Signed Certificate
34
+ cert = self.sign_certificate(csr)
35
+
36
+ degenerate_pkcs7 = OpenSSL::PKCS7.new()
37
+ degenerate_pkcs7.type="signed"
38
+ degenerate_pkcs7.certificates=[cert]
39
+ enc_cert = OpenSSL::PKCS7.encrypt(p7sign.certificates, degenerate_pkcs7.to_der,
40
+ OpenSSL::Cipher::Cipher::new("des-ede3-cbc"), OpenSSL::PKCS7::BINARY)
41
+ reply = OpenSSL::PKCS7.sign(SSL.certificate, SSL.key, enc_cert.to_der, [], OpenSSL::PKCS7::BINARY)
42
+
43
+ return Certificate.new(reply.to_der, "application/x-pki-message")
44
+ end
45
+
46
+ def verify_response(raw_postback_data)
47
+ p7sign = OpenSSL::PKCS7.new(raw_postback_data)
48
+ store = OpenSSL::X509::Store.new
49
+ p7sign.verify(nil, store, nil, OpenSSL::PKCS7::NOVERIFY)
50
+ return p7sign
51
+ end
52
+ def verify_signer(p7sign)
53
+ signers = p7sign.signers
54
+
55
+ return (signers[0].issuer.to_s == SSL.certificate.subject.to_s)
56
+ end
57
+
58
+
59
+ end
60
+ private
61
+ def self.sign_certificate(signing_request)
62
+ request = OpenSSL::X509::Request.new(signing_request)
63
+
64
+ # New Certificate
65
+ cert = OpenSSL::X509::Certificate.new
66
+ cert.version = 2
67
+ cert.serial = 1
68
+ cert.subject = request.subject
69
+ cert.issuer = SSL.certificate.subject
70
+ cert.public_key = request.public_key
71
+ cert.not_before = Time.now
72
+ cert.not_after = Time.now+(86400*1)
73
+
74
+ # Prepare to sign
75
+ ef = OpenSSL::X509::ExtensionFactory.new
76
+ ef.subject_certificate = cert
77
+ ef.issuer_certificate = SSL.certificate
78
+ cert.add_extension(ef.create_extension("keyUsage", "digitalSignature,keyEncipherment", true))
79
+ cert.sign(SSL.key, OpenSSL::Digest::SHA1.new)
80
+
81
+ return cert
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ module IOSCertEnrollment
2
+ module SSL
3
+ @@key, @@certificate = nil
4
+ class << self
5
+ def key
6
+ return @@key if @@key
7
+ return @@key = OpenSSL::PKey::RSA.new(File.read(IOSCertEnrollment.ssl_key_path))
8
+ end
9
+
10
+ def certificate
11
+ return @@certificate if @@certificate
12
+ return @@certificate = OpenSSL::X509::Certificate.new(File.read(IOSCertEnrollment.ssl_certificate_path))
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module IOSCertEnrollment
2
+ VERSION = '0.0.2'.freeze unless defined?(::IOSCertEnrollment::VERSION)
3
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ios-cert-enrollment
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Nolan Brown
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-10 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rake
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rdoc
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: uuidtools
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: plist
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ description: Easy tools to implement a SCEP server for iOS Configuration Profiles
77
+ email: nolanbrown@gmail.com
78
+ executables: []
79
+
80
+ extensions: []
81
+
82
+ extra_rdoc_files: []
83
+
84
+ files:
85
+ - lib/ios-cert-enrollment.rb
86
+ - lib/ios-cert-enrollment/certificate.rb
87
+ - lib/ios-cert-enrollment/configuration.rb
88
+ - lib/ios-cert-enrollment/device.rb
89
+ - lib/ios-cert-enrollment/profile.rb
90
+ - lib/ios-cert-enrollment/sign.rb
91
+ - lib/ios-cert-enrollment/ssl.rb
92
+ - lib/ios-cert-enrollment/version.rb
93
+ homepage: http://github.com/nolanbrown
94
+ licenses: []
95
+
96
+ post_install_message:
97
+ rdoc_options:
98
+ - --title
99
+ - iOS Portal
100
+ - --main
101
+ require_paths:
102
+ - lib
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ requirements: []
123
+
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.24
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: SCEP server for iOS Configuration Profiles
129
+ test_files: []
130
+