Class: VPNMaker::KeyBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/vpnmaker/key_builder.rb

Instance Method Summary collapse

Constructor Details

#initialize(tracker, config) ⇒ KeyBuilder

Returns a new instance of KeyBuilder.



3
4
5
6
7
8
# File 'lib/vpnmaker/key_builder.rb', line 3

def initialize(tracker, config)
  @tmpdir = '/tmp/keybuilder'
  clean_tmpdir
  @tracker = tracker
  @config = config
end

Instance Method Details

#build_caObject



62
63
64
65
66
67
68
69
70
# File 'lib/vpnmaker/key_builder.rb', line 62

def build_ca
  index = tmppath('index.txt')

  FileUtils.touch(index)

  `openssl req -batch -days 3650 -nodes -new -x509 -keyout #{@tmpdir}/ca.key -out #{@tmpdir}/ca.crt -config #{opensslcnf}`
  gen_crl
  @tracker.set_ca(tmpfile('ca.key'), tmpfile('ca.crt'), tmpfile('crl.pem'), tmpfile('index.txt'), "01\n")
end

#build_dh_key(keysize = 1024) ⇒ Object

Build Diffie-Hellman parameters for the server side of an SSL/TLS connection.



49
50
51
52
# File 'lib/vpnmaker/key_builder.rb', line 49

def build_dh_key(keysize=1024)
  `openssl dhparam -out #{tmppath('dh.pem')} #{keysize}`
  @tracker.set_dh(tmpfile('dh.pem'))
end

#build_key(user, name, email, pass, delegate) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/vpnmaker/key_builder.rb', line 100

def build_key(user, name, email, pass, delegate)
  h = {:key_cn => user, :key_name => name, :key_email => email}
  place_file('ca.crt')
  place_file('ca.key')
  place_file('index.txt')
  place_file('serial')
  if pass
    pass_spec = "-passin 'pass:#{pass}' -passout 'pass:#{pass}'"
  else
    pass_spec = '-nodes'
  end
  `openssl req -batch -days 3650 -new -keyout #{tmppath(user, 'key')} -out #{tmppath(user, 'csr')} -config #{opensslcnf(h)} -nodes`
  `openssl ca -batch -days 3650 -out #{tmppath(user, 'crt')} -in #{tmppath(user, 'csr')} -config #{opensslcnf(h)}`
  # TODO: this still asks for the export password and we hack
  # around it from bin/vpnmaker. This is actually something that
  # should only be generated dynamically upon user request.
  `openssl pkcs12 -export -clcerts -in #{tmppath(user, 'crt')} -inkey #{tmppath(user, 'key')} -out #{tmppath(user, 'p12')} #{pass_spec}`
  @tracker.send(delegate, user, name, email, tmpfile(user, 'key'), tmpfile(user, 'crt'), tmpfile(user, 'p12'), tmpfile('index.txt'), tmpfile('serial'))
end

#build_server_keyObject



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/vpnmaker/key_builder.rb', line 72

def build_server_key
  place_file('ca.crt')
  place_file('ca.key')
  place_file('index.txt')
  place_file('serial')

  `openssl req -batch -days 3650 -nodes -new -keyout #{tmppath('server.key')} -out #{tmppath('server.csr')} -extensions server -config #{opensslcnf}`
  `openssl ca -batch -days 3650 -out #{tmppath('server.crt')} -in #{tmppath('server.csr')} -extensions server -config #{opensslcnf}`

  @tracker.set_server_key(tmpfile('server.key'), tmpfile('server.crt'), tmpfile('index.txt'), tmpfile('serial'))
end

#build_ta_keyObject



84
85
86
87
# File 'lib/vpnmaker/key_builder.rb', line 84

def build_ta_key
  `openvpn --genkey --secret #{tmppath('ta.key')}`
  @tracker.set_ta_key(tmpfile('ta.key'))
end

#caObject



54
55
56
# File 'lib/vpnmaker/key_builder.rb', line 54

def ca
  @tracker[:ca]
end

#clean_tmpdirObject



10
11
12
13
# File 'lib/vpnmaker/key_builder.rb', line 10

def clean_tmpdir
  FileUtils.rm_rf(@tmpdir)
  FileUtils.mkdir_p(@tmpdir)
end

#cnfpathObject



15
# File 'lib/vpnmaker/key_builder.rb', line 15

def cnfpath; "/tmp/openssl-#{$$}.cnf"; end

#gen_crlObject



58
59
60
# File 'lib/vpnmaker/key_builder.rb', line 58

def gen_crl
  `openssl ca -gencrl -crldays 3650 -keyfile #{tmppath('ca.key')} -cert #{tmppath('ca.crt')} -out #{tmppath('crl.pem')} -config #{opensslcnf}`
end

#initObject



33
34
35
36
# File 'lib/vpnmaker/key_builder.rb', line 33

def init
  `touch #{@dir}/index.txt`
  `echo 01 > #{@dir}/serial`
end

#opensslcnf(hash = {}) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/vpnmaker/key_builder.rb', line 38

def opensslcnf(hash={})
  c = cnfpath

  File.open(cnfpath, 'w') do |f|
    f.write(Haml::Engine.new(File.read(@tracker.path + "/" + @config[:site][:template_dir] + "/" + 'openssl.haml')).render(Object.new, opensslvars.merge(hash)))
  end

  c
end

#opensslvarsObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/vpnmaker/key_builder.rb', line 17

def opensslvars
  {
    :key_size => 1024,
    :key_dir => @tmpdir,
    :key_country => @config[:key_properties][:country],
    :key_province => @config[:key_properties][:province],
    :key_city => @config[:key_properties][:city],
    :key_org => @config[:key_properties][:organization],
    :key_email => @config[:key_properties][:email],
    :key_org => @config[:key_properties][:organization],
    :key_ou => @config[:key_properties][:organization_unit],
    :key_cn => @config[:key_properties][:common_name],
    :key_name => @config[:key_properties][:name]
  }
end

#place_file(name) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/vpnmaker/key_builder.rb', line 89

def place_file(name)
  if data = @tracker.db.data(name)
    File.open(File.join(@tmpdir, name), 'w') {|f| f.write(data)}
  else
    raise "No data for #{name}"
  end
end

#revoke_key(user, version) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/vpnmaker/key_builder.rb', line 120

def revoke_key(user, version)
  h = {:key_cn => ""}
  place_file('ca.crt')
  place_file('ca.key')
  place_file('crl.pem')
  place_file('index.txt')
  place_file('serial')

  user_crt = tmppath(user, 'crt')
  rev_crt = tmppath('rev-test.crt')
  File.open(user_crt, 'w') {|f| f.write(@tracker.key(user, version, 'crt'))}
  `openssl ca -revoke #{user_crt} -keyfile #{tmppath('ca.key')} -cert #{tmppath('ca.crt')} -config #{opensslcnf(h)}`
  gen_crl

  File.open(rev_crt, 'w') {|f| f.write(File.read(tmppath('ca.crt'))); f.write(File.read(tmppath('crl.pem')))}
  if `openssl verify -CAfile #{rev_crt} -crl_check #{user_crt}` =~ /certificate revoked/
    @tracker.user_key_revoked(user, version, tmpfile('crl.pem'), tmpfile('index.txt'))
  else
    raise "Revocation verification failed: openssl isn't recognizing it"
  end
end

#tmpfile(*args) ⇒ Object



98
# File 'lib/vpnmaker/key_builder.rb', line 98

def tmpfile(*args); File.read(tmppath(*args)); end

#tmppath(f, extn = nil) ⇒ Object



97
# File 'lib/vpnmaker/key_builder.rb', line 97

def tmppath(f, extn=nil); File.join(@tmpdir, extn ? "#{f}.#{extn}" : f); end