ovpnmcgen.rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c5cb5752cb5bbfd9b9db08e87949e0807c250c3
4
+ data.tar.gz: 349c51df8ade0b4d5aea93276068dd491c379c67
5
+ SHA512:
6
+ metadata.gz: c37390ffe65b3b17a535aa0a434663e63fba3a8d8f2415e7e130dbb78acef5d6d98bf091d17ccfc9ef22ab33fb54801d8e552deb4745f91650a5976de328e67c
7
+ data.tar.gz: a7b2706e22de7978969a5327278978d869e7a5eb649f6c5b9e2c97c945a13723637c1e5a09f2dca2c1cfa426f284690a06b5bd75b4577ad8bf5d1c104401b4fd
@@ -0,0 +1,18 @@
1
+ DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
@@ -0,0 +1 @@
1
+ ovpnmcgen
@@ -0,0 +1 @@
1
+ ruby-2.1.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ovpnmcgen.rb.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ronald Ip
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ # Ovpnmcgen.rb
2
+
3
+ OpenVPN iOS Configuration Profile Utility
4
+
5
+ This utility generates configuration profiles that enables VPN-on-Demand, as documented by Apple in <https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010206-CH1-SW27>.
6
+
7
+ ## Installation
8
+
9
+ Install it yourself as:
10
+
11
+ $ gem install ovpnmcgen.rb
12
+
13
+ ## Usage
14
+
15
+ ### Typical Usage
16
+ $ ovpnmcgen.rb gen --trusted-ssids home --host vpn.example.com --cafile path/to/ca.pem --tafile path/to/ta.key --p12file path/to/john-ipad.p12 --p12pass p12passphrase john ipad
17
+
18
+ ### Extended Usage
19
+ $ ovpnmcgen.rb gen --trusted-ssids home,school --untrusted-ssids virusnet --host vpn.example.com --cafile path/to/ca.pem --tafile path/to/ta.key --p12file path/to/john-ipad.p12 --p12pass p12passphrase john ipad
20
+
21
+ ### Using OpenSSL to generate a PKCS#12 file
22
+ openssl pkcs12 -export -out path/to/john-ipad.p12 -inkey path/to/john-ipad.key -in path/to/john-ipad.crt -passout pass:p12passphrase
23
+
24
+ ## Contributing
25
+
26
+ 1. Fork it (<http://github.com/iphoting/ovpnmcgen.rb/fork>)
27
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
28
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
29
+ 4. Push to the branch (`git push origin my-new-feature`)
30
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ovpnmcgen'
4
+ require 'commander/import'
5
+
6
+ program :version, Ovpnmcgen::VERSION
7
+ program :description, Ovpnmcgen::SUMMARY
8
+ program :help, 'Usage', 'ovpnmcgen.rb <command> [options] <args...>'
9
+ program :help_formatter, :compact
10
+ default_command :help
11
+ never_trace!
12
+ #global_option '-c', '--config FILE', 'Specify path to config file' #not implemented yet
13
+
14
+ command :generate do |c|
15
+ c.syntax = 'ovpnmcgen.rb generate [options] <user> <device>'
16
+ c.summary = 'Generates iOS Configuration Profiles'
17
+ c.description = 'Generates a .mobileconfig plist.'
18
+ c.example 'Typical Usage', 'ovpnmcgen.rb gen --trusted-ssids home --host vpn.example.com --cafile path/to/ca.pem --tafile path/to/ta.key --p12file path/to/john-ipad.p12 --p12pass p12passphrase john ipad'
19
+ c.example 'Extended Usage', 'ovpnmcgen.rb gen --trusted-ssids home,school --untrusted-ssids virusnet --host vpn.example.com --cafile path/to/ca.pem --tafile path/to/ta.key --p12file path/to/john-ipad.p12 --p12pass p12passphrase john ipad'
20
+ c.example 'Creating a .p12 file using OpenSSL', 'openssl pkcs12 -export -out path/to/john-ipad.p12 -inkey path/to/john-ipad.key -in path/to/john-ipad.crt -passout pass:p12passphrase'
21
+ c.option '--cafile FILE', 'Path to OpenVPN CA file. (Required)'
22
+ c.option '--tafile FILE', 'Path to TLS Key file. (Required)'
23
+ c.option '--host HOSTNAME', 'Hostname of OpenVPN server. (Required)'
24
+ c.option '--p12file FILE', 'Path to user PKCS#12 file. (Required)'
25
+ c.option '--p12pass PASSWORD', 'Password to unlock PKCS#12 file.'
26
+ c.option '--[no-]vod', 'Enable or Disable VPN-On-Demand. [Default: Enabled]'
27
+ c.option '--trusted-ssids SSIDS', Array, 'List of comma-separated trusted SSIDs.'
28
+ c.option '--untrusted-ssids SSIDS', Array, 'List of comma-separated untrusted SSIDs.'
29
+ c.option '-o', '--output FILE', 'Output to file. [Default: stdout]'
30
+ c.action do |args, options|
31
+ raise ArgumentError.new "Invalid arguments. Run #{File.basename(__FILE__)} help for guidance." if args.nil? or args.length < 2
32
+ raise ArgumentError.new "Host is required." unless options.host
33
+ raise ArgumentError.new "cafile is required." unless options.cafile
34
+ raise ArgumentError.new "tafile is required." unless options.tafile
35
+ raise ArgumentError.new "PKCS#12 file is required." unless options.p12file
36
+ options.default :vod => true
37
+ user, device, p12file, p12pass = args
38
+ inputs = {
39
+ :user => user,
40
+ :device => device,
41
+ :p12file => options.p12file,
42
+ :p12pass => options.p12pass,
43
+ :cafile => options.cafile,
44
+ :tafile => options.tafile,
45
+ :host => options.host,
46
+ :enableVOD => options.vod,
47
+ :trusted_ssids => options.trusted_ssids,
48
+ :untrusted_ssids => options.untrusted_ssids
49
+ }
50
+ unless options.output
51
+ puts Ovpnmcgen.generate(inputs)
52
+ else
53
+ # write to file
54
+ begin
55
+ File.write(options.output, Ovpnmcgen.generate(inputs))
56
+ rescue Errno::ENOENT
57
+ puts "Error writing to: #{options.output}"
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ alias_command :g, :generate
64
+ alias_command :gen, :generate
@@ -0,0 +1,133 @@
1
+ require "ovpnmcgen/version"
2
+ require 'plist'
3
+ require 'base64'
4
+
5
+ module Ovpnmcgen
6
+ class StringData < String
7
+ def to_plist_node
8
+ return "<data>\n#{self}\n</data>"
9
+ end
10
+ end
11
+
12
+ def generate(inputs = {})
13
+ identifier = inputs[:identifier] || inputs[:host].split('.').reverse!.join('.')
14
+ port = inputs[:port] || 1194
15
+ certUUID = inputs[:certUUID] || `uuidgen`.chomp.upcase
16
+ user, device, domain, host = inputs[:user], inputs[:device], inputs[:host], inputs[:host]
17
+ enableVOD = inputs[:enableVOD]
18
+ p12pass = inputs[:p12pass] || ''
19
+ trusted_ssids = inputs[:trusted_ssids] || false
20
+ untrusted_ssids = inputs[:untrusted_ssids] || false
21
+
22
+ begin
23
+ ca_cert = File.readlines(inputs[:cafile]).map { |x| x.chomp }.join('\n')
24
+ rescue Errno::ENOENT
25
+ puts "CA file not found: #{inputs[:cafile]}!"
26
+ exit
27
+ end
28
+
29
+ begin
30
+ tls_auth = File.readlines(inputs[:tafile]).map { |x| x.chomp }.join('\n')
31
+ rescue Errno::ENOENT
32
+ puts "TLS file not found: #{inputs[:tafile]}!"
33
+ exit
34
+ end
35
+
36
+ begin
37
+ p12file = Base64.encode64(File.read(inputs[:p12file]))
38
+ rescue Errno::ENOENT
39
+ puts "PCKS#12 file not found: #{inputs[:p12file]}!"
40
+ exit
41
+ end
42
+
43
+ vpnOnDemandRules = Array.new
44
+ vodTrusted = { # Trust only Wifi SSID
45
+ 'SSIDMatch' => trusted_ssids,
46
+ 'Action' => 'Disconnect'
47
+ }
48
+ vodUntrusted = { # Untrust Wifi
49
+ 'SSIDMatch' => untrusted_ssids,
50
+ 'Action' => 'Connect'
51
+ }
52
+ vpnOnDemandRules << vodTrusted if trusted_ssids
53
+ vpnOnDemandRules << vodUntrusted if untrusted_ssids
54
+
55
+ vpnOnDemandRules << { # Untrust all Wifi
56
+ 'InterfaceTypeMatch' => 'WiFi',
57
+ 'Action' => 'Connect'
58
+ } << { # Trust Cellular
59
+ 'InterfaceTypeMatch' => 'Cellular',
60
+ 'Action' => 'Ignore'
61
+ } << { # Default catch-all
62
+ 'Action' => 'Connect'
63
+ }
64
+
65
+ cert = {
66
+ 'Password' => p12pass,
67
+ 'PayloadCertificateFileName' => "#{user}-#{device}.p12",
68
+ 'PayloadContent' => StringData.new(p12file),
69
+ 'PayloadDescription' => 'Provides device authentication (certificate or identity).',
70
+ 'PayloadDisplayName' => "#{user}-#{device}.p12",
71
+ 'PayloadIdentifier' => "#{identifier}.#{user}-#{device}.credential",
72
+ 'PayloadOrganization' => domain,
73
+ 'PayloadType' => 'com.apple.security.pkcs12',
74
+ 'PayloadUUID' => certUUID,
75
+ 'PayloadVersion' => 1
76
+ }
77
+
78
+ vpn = {
79
+ 'PayloadDescription' => "Configures VPN settings, including authentication.",
80
+ 'PayloadDisplayName' => "VPN (#{host}/VoD)",
81
+ 'PayloadIdentifier' => "#{identifier}.#{user}-#{device}.vpnconfig",
82
+ 'PayloadOrganization' => domain,
83
+ 'PayloadType' => 'com.apple.vpn.managed',
84
+ 'PayloadUUID' => `uuidgen`.chomp.upcase,
85
+ 'PayloadVersion' => 1,
86
+ 'UserDefinedName' => "#{host}/VoD",
87
+ 'VPN' => {
88
+ 'AuthenticationMethod' => 'Certificate',
89
+ 'OnDemandEnabled' => (enableVOD)? 1 : 0,
90
+ 'OnDemandRules' => vpnOnDemandRules,
91
+ 'PayloadCertificateUUID' => certUUID,
92
+ 'RemoteAddress' => 'DEFAULT'
93
+ },
94
+ 'VPNSubType' => 'net.openvpn.OpenVPN-Connect.vpnplugin',
95
+ 'VPNType' => 'VPN',
96
+ 'VendorConfig' => {
97
+ 'ca' => ca_cert,
98
+ 'client' => 'NOARGS',
99
+ 'comp-lzo' => 'NOARGS',
100
+ 'dev' => 'tun',
101
+ 'key-direction' => '1',
102
+ 'persist-key' => 'NOARGS',
103
+ 'persist-tun' => 'NOARGS',
104
+ 'proto' => 'udp',
105
+ 'remote' => "#{host} #{port} udp",
106
+ 'remote-cert-tls' => 'server',
107
+ 'resolv-retry' => 'infinite',
108
+ 'tls-auth' => tls_auth,
109
+ 'verb' => '3'
110
+ }
111
+ }
112
+
113
+ plistPayloadContent = [vpn, cert] # to encrypt this array
114
+ #encPlistPayloadContent = cmsEncrypt([vpn, cert].to_plist).der_format
115
+
116
+ plist = {
117
+ 'PayloadDescription' => "OpenVPN Configuration Payload for #{user}-#{device}@#{host}",
118
+ 'PayloadDisplayName' => "#{host} OpenVPN #{user}@#{device}",
119
+ 'PayloadIdentifier' => "#{identifier}.#{user}-#{device}",
120
+ 'PayloadOrganization' => domain,
121
+ 'PayloadRemovalDisallowed' => false,
122
+ 'PayloadType' => 'Configuration',
123
+ 'PayloadUUID' => `uuidgen`.chomp.upcase,
124
+ 'PayloadVersion' => 1,
125
+ #'EncryptedPayloadContent' => StringData.new(encPlistPayloadContent)
126
+ 'PayloadContent' => plistPayloadContent
127
+ }
128
+
129
+ return plist.to_plist
130
+ end
131
+
132
+ module_function :generate
133
+ end
@@ -0,0 +1,4 @@
1
+ module Ovpnmcgen
2
+ VERSION = "0.0.1"
3
+ SUMMARY = "OpenVPN iOS Configuration Profile Utility"
4
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ovpnmcgen/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ovpnmcgen.rb"
8
+ spec.version = Ovpnmcgen::VERSION
9
+ spec.authors = ["Ronald Ip"]
10
+ spec.email = ["myself@iphoting.com"]
11
+ spec.summary = Ovpnmcgen::SUMMARY
12
+ spec.description = "This utility generates configuration profiles that enables VPN-on-Demand, as documented by Apple in https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010206-CH1-SW27"
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+ spec.bindir = 'bin'
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.5"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_runtime_dependency "plist"
25
+ spec.add_runtime_dependency "commander", "~> 4.1"
26
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ovpnmcgen.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ronald Ip
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: plist
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: commander
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.1'
69
+ description: This utility generates configuration profiles that enables VPN-on-Demand,
70
+ as documented by Apple in https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010206-CH1-SW27
71
+ email:
72
+ - myself@iphoting.com
73
+ executables:
74
+ - ovpnmcgen.rb
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".ruby-gemset"
80
+ - ".ruby-version"
81
+ - Gemfile
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - bin/ovpnmcgen.rb
86
+ - lib/ovpnmcgen.rb
87
+ - lib/ovpnmcgen/version.rb
88
+ - ovpnmcgen.rb.gemspec
89
+ homepage: ''
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.2.2
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: OpenVPN iOS Configuration Profile Utility
113
+ test_files: []