yopass 2.2.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.gemspec +4 -4
  3. data/Dockerfile +9 -14
  4. data/Gemfile +2 -1
  5. data/Gemfile.lock +3 -2
  6. data/README.md +41 -17
  7. data/lib/public/create-secret.html +32 -0
  8. data/lib/public/css/bootstrap.min.css +5 -0
  9. data/lib/public/display-secret.html +34 -0
  10. data/lib/public/fonts/glyphicons-halflings-regular.eot +0 -0
  11. data/lib/public/fonts/glyphicons-halflings-regular.svg +288 -0
  12. data/lib/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  13. data/lib/public/fonts/glyphicons-halflings-regular.woff +0 -0
  14. data/lib/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  15. data/lib/public/index.html +49 -0
  16. data/lib/public/js/angular-route.min.js +15 -0
  17. data/lib/public/js/angular.js +250 -0
  18. data/lib/public/js/app.js +65 -0
  19. data/lib/yopass.rb +75 -80
  20. data/spec/yopass_spec.rb +22 -15
  21. metadata +25 -52
  22. data/CHANGELOG.md +0 -39
  23. data/Procfile +0 -1
  24. data/conf/config.ru +0 -3
  25. data/conf/yopass.yaml +0 -10
  26. data/lib/static/flash/clippy.swf +0 -0
  27. data/lib/static/js/jquery.address.js +0 -598
  28. data/lib/static/js/jquery.js +0 -8829
  29. data/lib/static/packaged/css/font.css +0 -36
  30. data/lib/static/packaged/css/semantic.css +0 -17804
  31. data/lib/static/packaged/css/semantic.min.css +0 -14
  32. data/lib/static/packaged/fonts/basic.icons.eot +0 -0
  33. data/lib/static/packaged/fonts/basic.icons.svg +0 -450
  34. data/lib/static/packaged/fonts/basic.icons.ttf +0 -0
  35. data/lib/static/packaged/fonts/basic.icons.woff +0 -0
  36. data/lib/static/packaged/fonts/icons.eot +0 -0
  37. data/lib/static/packaged/fonts/icons.otf +0 -0
  38. data/lib/static/packaged/fonts/icons.svg +0 -399
  39. data/lib/static/packaged/fonts/icons.ttf +0 -0
  40. data/lib/static/packaged/fonts/icons.woff +0 -0
  41. data/lib/static/packaged/fonts/sans/OpenSans-Bold.ttf +0 -0
  42. data/lib/static/packaged/fonts/sans/OpenSans-Light.ttf +0 -0
  43. data/lib/static/packaged/fonts/sans/OpenSans.ttf +0 -0
  44. data/lib/static/packaged/fonts/sans/OpenSansLight-Italic.ttf +0 -0
  45. data/lib/static/packaged/fonts/sans/SourceSansPro-Bold.ttf +0 -0
  46. data/lib/static/packaged/fonts/sans/SourceSansPro-Regular.ttf +0 -0
  47. data/lib/static/packaged/images/loader-large-inverted.gif +0 -0
  48. data/lib/static/packaged/images/loader-large.gif +0 -0
  49. data/lib/static/packaged/images/loader-medium-inverted.gif +0 -0
  50. data/lib/static/packaged/images/loader-medium.gif +0 -0
  51. data/lib/static/packaged/images/loader-mini-inverted.gif +0 -0
  52. data/lib/static/packaged/images/loader-mini.gif +0 -0
  53. data/lib/static/packaged/images/loader-small-inverted.gif +0 -0
  54. data/lib/static/packaged/images/loader-small.gif +0 -0
  55. data/lib/static/packaged/javascript/semantic.js +0 -11944
  56. data/lib/static/packaged/javascript/semantic.min.js +0 -16
  57. data/lib/static/yopass.css +0 -23
  58. data/lib/static/yopass.js +0 -23
  59. data/lib/views/404.erb +0 -43
  60. data/lib/views/footer.erb +0 -9
  61. data/lib/views/get_secret.erb +0 -31
  62. data/lib/views/header.erb +0 -27
  63. data/lib/views/index.erb +0 -117
  64. data/lib/views/secret_url.erb +0 -87
  65. data/yopass.god +0 -11
data/lib/yopass.rb CHANGED
@@ -2,77 +2,86 @@ require 'memcached'
2
2
  require 'sinatra/base'
3
3
  require 'securerandom'
4
4
  require 'encryptor'
5
- require 'yaml'
6
5
  require 'uri'
7
6
  require 'yopass/sms_provider'
7
+ require 'sinatra/json'
8
+ require 'json'
9
+
10
+ def too_many_tries?(m, key)
11
+ key += key + '_ratelimit'
12
+ begin
13
+ result = m.get key
14
+ rescue Memcached::NotFound
15
+ m.set key, 1, 3600 * 24
16
+ return false
17
+ end
18
+ m.set key, result + 1
19
+
20
+ # This dude has tried to many times...
21
+ true if result >= 2
22
+ end
8
23
 
9
- # Share your secrets securely
10
24
  class Yopass < Sinatra::Base
25
+ helpers Sinatra::JSON
26
+
11
27
  configure :development do
12
28
  require 'sinatra/reloader'
13
29
  register Sinatra::Reloader
14
30
  end
15
31
 
16
32
  configure do
17
- config = ENV['YOPASS_CONFIG'] || 'conf/yopass.yaml'
18
- cfg = YAML.load_file(config)
19
- set :config, cfg
20
- set :base_url, ENV['YOPASS_BASE_URL'] || cfg['base_url']
21
- set :public_folder, File.dirname(__FILE__) + '/static'
22
- set :mc, Memcached.new(ENV['YOPASS_MEMCACHED_URL'] || cfg['memcached_url'])
23
- end
24
-
25
- get '/' do
26
- # display mobile number field if send_sms is true
27
- erb :index, locals: { send_sms: settings.config['send_sms'], error: nil }
28
- end
29
-
30
- get '/:key' do
31
- erb :get_secret, locals: { key: params[:key] }
33
+ set :public_folder, File.dirname(__FILE__) + '/public'
34
+ set :max_length, 10000
35
+ if ENV['YP_SECRET_MAX_LENGTH']
36
+ set :max_length, ENV['YP_SECRET_MAX_LENGTH'].to_i
37
+ end
32
38
  end
33
39
 
34
- get '/:key/:password' do
35
- # Disable all caching
36
- headers 'Cache-Control' => 'no-cache, no-store, must-revalidate'
37
- headers 'Pragma' => 'no-cache'
38
- headers 'Expires' => '0'
39
-
40
+ get '/v1/secret/:key/:password' do
41
+ m = Memcached.new(ENV['YP_MEMCACHED'] || 'localhost:11211')
40
42
  begin
41
- result = settings.mc.get params[:key]
43
+ result = m.get params[:key]
42
44
  rescue Memcached::NotFound
43
- return erb :'404'
45
+ status 404
46
+ return json message: 'Not found'
44
47
  end
45
- content_type 'text/plain'
46
48
 
47
49
  begin
48
50
  result = Encryptor.decrypt(value: result, key: params[:password])
49
51
  rescue OpenSSL::Cipher::CipherError
50
- settings.mc.delete(params[:key]) if too_many_tries?(params[:key])
51
- return 'Invalid decryption key'
52
+ m.delete(params[:key]) if too_many_tries?(m, params[:key])
53
+ status 401
54
+ return json message: 'Invalid decryption key'
52
55
  end
53
- settings.mc.delete params[:key]
54
- result
56
+ m.delete params[:key]
57
+ return json secret: result
55
58
  end
56
59
 
57
- post '/' do
58
- headers 'Cache-Control' => 'no-cache, no-store, must-revalidate'
59
- headers 'Pragma' => 'no-cache'
60
- headers 'Expires' => '0'
60
+ post '/v1/secret' do
61
+ begin
62
+ r = JSON.parse(request.body.read)
63
+ rescue JSON::ParserError
64
+ status 400
65
+ return json message: 'Bad request, seek API docs at https://github.com/jhaals/yopass'
66
+ end
61
67
 
62
- lifetime = params[:lifetime]
68
+ lifetime = r['lifetime']
63
69
  # calculate lifetime in secounds
64
70
  lifetime_options = { '1w' => 3600 * 24 * 7,
65
71
  '1d' => 3600 * 24,
66
72
  '1h' => 3600 }
67
73
 
68
74
  # Verify that user has posted a valid lifetime
69
- return 'Invalid lifetime' unless lifetime_options.include? lifetime
70
- return 'No secret submitted' if params[:secret].empty?
71
-
72
- if params[:secret].length >= settings.config['secret_max_length']
73
- return erb :index, locals: {
74
- send_sms: settings.config['send_sms'],
75
- error: 'This site is meant to store secrets not novels' }
75
+ status 400
76
+ # default lifetime
77
+ lifetime = '1d' if lifetime.nil?
78
+ secret = r['secret']
79
+ return json message: 'Invalid lifetime' unless lifetime_options.include? lifetime
80
+ return json message: 'No secret submitted' if secret.nil?
81
+ return json message: 'No secret submitted' if secret.empty?
82
+
83
+ if secret.length >= settings.max_length
84
+ return json message: 'error: This site is meant to store secrets not novels'
76
85
  end
77
86
 
78
87
  # goes in URL
@@ -80,54 +89,40 @@ class Yopass < Sinatra::Base
80
89
  # decryption_key goes in URL or via SMS if provider is configured
81
90
  decryption_key = SecureRandom.hex[0..8]
82
91
  # encrypt secret with generated decryption_key
83
- data = Encryptor.encrypt(params[:secret], key: decryption_key)
92
+ data = Encryptor.encrypt(secret, key: decryption_key)
84
93
 
94
+ m = Memcached.new(ENV['YP_MEMCACHED'] || 'localhost:11211')
85
95
  # store secret in memcached
86
96
  begin
87
- settings.mc.set key, data, lifetime_options[lifetime]
97
+ m.set key, data, lifetime_options[lifetime]
88
98
  rescue Memcached::ServerIsMarkedDead
89
- return erb :index, locals: {
90
- send_sms: settings.config['send_sms'],
91
- error: 'Error: Unable to contact memcached' }
99
+ status 500
100
+ return json message: 'Error: Unable to contact memcached'
92
101
  end
93
-
94
- if settings.config['send_sms'] == true && !params[:mobile_number].nil?
95
- # strip everything except digits
96
- mobile_number = params[:mobile_number].gsub(/[^0-9]/, '')
97
- # load specified sms provider
98
- sms = SmsProvider.create(settings.config['sms::provider'],
99
- settings.config['sms::settings'])
100
-
101
- unless params[:mobile_number].empty?
102
+ mobile_number = r['mobile_number']
103
+ if ENV['YP_SEND_SMS'] && !mobile_number.nil?
104
+ unless mobile_number.empty?
105
+ # strip everything except digits
106
+ mobile_number = mobile_number.gsub(/[^0-9]/, '')
107
+ # load SMS provider
108
+ sms_settings = JSON.parse(ENV['YP_SMS_SETTINGS'])
109
+ sms = SmsProvider.create(
110
+ sms_settings['provider'],
111
+ sms_settings['settings'])
102
112
  sms.send(mobile_number, decryption_key)
103
- return erb :secret_url, locals: {
104
- full_url: URI.join(settings.base_url, key + '/' + decryption_key),
105
- short_url: URI.join(settings.base_url, key),
106
- decryption_key: decryption_key,
107
- key_sent_to_mobile: true }
108
113
  end
109
114
  end
110
-
111
- erb :secret_url, locals: {
112
- full_url: URI.join(settings.base_url, key + '/' + decryption_key),
113
- short_url: URI.join(settings.base_url, key),
115
+ status 200
116
+ json key: key,
114
117
  decryption_key: decryption_key,
115
- key_sent_to_mobile: false }
118
+ full_url: "/v1/secret/#{key}/#{decryption_key}",
119
+ short_url: "/v1/secret/#{key}",
120
+ message: 'secret stored'
116
121
  end
117
- run! if app_file == $PROGRAM_NAME
118
- end
119
122
 
120
- def too_many_tries?(key)
121
- key += key + '_ratelimit'
122
- begin
123
- result = settings.mc.get key
124
- rescue Memcached::NotFound
125
- settings.mc.set key, 1, 3600 * 24
126
- return false
123
+ get '/' do
124
+ # Ugly way of serving index...
125
+ File.read(File.join(settings.public_folder, 'index.html'))
127
126
  end
128
- settings.mc.set key, result + 1
129
-
130
- # This dude has tried to many times...
131
- return true if result >= 2
132
- false
127
+ run! if app_file == $PROGRAM_NAME
133
128
  end
data/spec/yopass_spec.rb CHANGED
@@ -1,49 +1,56 @@
1
1
  require 'spec_helper'
2
-
2
+ require 'json'
3
3
  describe 'yopass' do
4
4
 
5
- it 'expect give the website' do
6
- get '/'
7
- expect(last_response.body).to match(/Share Secrets Securely/)
8
- end
9
-
10
5
  it 'expect complain about invalid lifetime' do
11
- post '/', 'lifetime' => 'foo'
6
+ post '/v1/secret', JSON.dump('lifetime' => 'foo')
12
7
  expect(last_response.body).to match(/Invalid lifetime/)
8
+ expect(last_response.status).to eq 400
13
9
  end
14
10
 
15
11
  it 'expect complain about missing secret' do
16
- post '/', 'lifetime' => '1h', 'secret' => ''
12
+ post '/v1/secret', JSON.dump('lifetime' => '1h', 'secret' => '')
17
13
  expect(last_response.body).to match(/No secret submitted/)
14
+ expect(last_response.status).to eq 400
15
+
18
16
  end
19
17
 
20
18
  it 'expect complain about secret being to long' do
21
- post '/', 'lifetime' => '1h', 'secret' => '0' * 1000000
19
+ post '/v1/secret', JSON.dump('lifetime' => '1h', 'secret' => '0' * 10000)
22
20
  expect(last_response.body).to match(/This site is meant to store secrets not novels/)
21
+ expect(last_response.status).to eq 400
23
22
  end
24
23
 
25
24
  it 'expect complain about not being able to connect to memcached' do
26
25
  allow_any_instance_of(Memcached).to receive(:set).and_raise(Memcached::ServerIsMarkedDead)
27
- post '/', 'lifetime' => '1h', 'secret' => '0' * 100
26
+ post '/v1/secret', JSON.dump('lifetime' => '1h', 'secret' => '0' * 100)
28
27
  expect(last_response.body).to match(/Unable to contact memcached/)
28
+ expect(last_response.status).to eq 500
29
29
  end
30
30
 
31
31
  it 'expect store secret' do
32
32
  allow_any_instance_of(Memcached).to receive(:set).and_return true
33
- post '/', 'lifetime' => '1h', 'secret' => '0' * 100
34
- expect(last_response.body).to match(/http:\/\/127.0.0.1:4567/)
33
+ post '/v1/secret', JSON.dump('lifetime' => '1h', 'secret' => 'test')
34
+
35
+ expect(last_response.body).to match(/full_url/)
36
+ expect(last_response.body).to match(/decryption_key/)
37
+ expect(last_response.body).to match(/key/)
38
+ expect(last_response.body).to match(/short_url/)
39
+ expect(last_response.status).to eq 200
35
40
  end
36
41
 
37
42
  it 'expect receive secret' do
38
43
  allow_any_instance_of(Memcached).to receive(:get).and_return("\xD5\x9E\xF7\xB1\xA0\xEC\xD6\xBD\xCA\x00nW\xAD\xB3\xF4\xDA")
39
44
  allow_any_instance_of(Memcached).to receive(:delete).and_return true
40
- get '/8937c6de9fb7b0ba9b7652b769743b4e/3af71378a'
45
+ get '/v1/secret/8937c6de9fb7b0ba9b7652b769743b4e/3af71378a'
41
46
  expect(last_response.body).to match(/hello world/)
47
+ expect(last_response.status).to eq 200
42
48
  end
43
49
 
44
50
  it 'expect raise Memcached::NotFound' do
45
51
  allow_any_instance_of(Memcached).to receive(:get).and_raise(Memcached::NotFound)
46
- get '/mykey/123'
47
- expect(last_response.body).to match(/Secret does not exist/)
52
+ get '/v1/secret/mykey/123'
53
+ expect(last_response.body).to match(/Not found/)
54
+ expect(last_response.status).to eq 404
48
55
  end
49
56
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yopass
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johan Haals
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-24 00:00:00.000000000 Z
11
+ date: 2015-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: encryptor
@@ -42,16 +42,22 @@ dependencies:
42
42
  name: rack
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.5.0
48
+ - - "<"
46
49
  - !ruby/object:Gem::Version
47
- version: '1.5'
50
+ version: '1.6'
48
51
  type: :runtime
49
52
  prerelease: false
50
53
  version_requirements: !ruby/object:Gem::Requirement
51
54
  requirements:
52
- - - "~>"
55
+ - - ">="
53
56
  - !ruby/object:Gem::Version
54
- version: '1.5'
57
+ version: 1.5.0
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.6'
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: sinatra
57
63
  requirement: !ruby/object:Gem::Requirement
@@ -73,7 +79,7 @@ dependencies:
73
79
  - - "~>"
74
80
  - !ruby/object:Gem::Version
75
81
  version: '1.4'
76
- type: :development
82
+ type: :runtime
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
@@ -117,56 +123,25 @@ files:
117
123
  - ".gemspec"
118
124
  - ".gitignore"
119
125
  - ".travis.yml"
120
- - CHANGELOG.md
121
126
  - Dockerfile
122
127
  - Gemfile
123
128
  - Gemfile.lock
124
129
  - LICENSE
125
- - Procfile
126
130
  - README.md
127
131
  - Rakefile
128
- - conf/config.ru
129
- - conf/yopass.yaml
130
132
  - config.ru
131
- - lib/static/flash/clippy.swf
132
- - lib/static/js/jquery.address.js
133
- - lib/static/js/jquery.js
134
- - lib/static/packaged/css/font.css
135
- - lib/static/packaged/css/semantic.css
136
- - lib/static/packaged/css/semantic.min.css
137
- - lib/static/packaged/fonts/basic.icons.eot
138
- - lib/static/packaged/fonts/basic.icons.svg
139
- - lib/static/packaged/fonts/basic.icons.ttf
140
- - lib/static/packaged/fonts/basic.icons.woff
141
- - lib/static/packaged/fonts/icons.eot
142
- - lib/static/packaged/fonts/icons.otf
143
- - lib/static/packaged/fonts/icons.svg
144
- - lib/static/packaged/fonts/icons.ttf
145
- - lib/static/packaged/fonts/icons.woff
146
- - lib/static/packaged/fonts/sans/OpenSans-Bold.ttf
147
- - lib/static/packaged/fonts/sans/OpenSans-Light.ttf
148
- - lib/static/packaged/fonts/sans/OpenSans.ttf
149
- - lib/static/packaged/fonts/sans/OpenSansLight-Italic.ttf
150
- - lib/static/packaged/fonts/sans/SourceSansPro-Bold.ttf
151
- - lib/static/packaged/fonts/sans/SourceSansPro-Regular.ttf
152
- - lib/static/packaged/images/loader-large-inverted.gif
153
- - lib/static/packaged/images/loader-large.gif
154
- - lib/static/packaged/images/loader-medium-inverted.gif
155
- - lib/static/packaged/images/loader-medium.gif
156
- - lib/static/packaged/images/loader-mini-inverted.gif
157
- - lib/static/packaged/images/loader-mini.gif
158
- - lib/static/packaged/images/loader-small-inverted.gif
159
- - lib/static/packaged/images/loader-small.gif
160
- - lib/static/packaged/javascript/semantic.js
161
- - lib/static/packaged/javascript/semantic.min.js
162
- - lib/static/yopass.css
163
- - lib/static/yopass.js
164
- - lib/views/404.erb
165
- - lib/views/footer.erb
166
- - lib/views/get_secret.erb
167
- - lib/views/header.erb
168
- - lib/views/index.erb
169
- - lib/views/secret_url.erb
133
+ - lib/public/create-secret.html
134
+ - lib/public/css/bootstrap.min.css
135
+ - lib/public/display-secret.html
136
+ - lib/public/fonts/glyphicons-halflings-regular.eot
137
+ - lib/public/fonts/glyphicons-halflings-regular.svg
138
+ - lib/public/fonts/glyphicons-halflings-regular.ttf
139
+ - lib/public/fonts/glyphicons-halflings-regular.woff
140
+ - lib/public/fonts/glyphicons-halflings-regular.woff2
141
+ - lib/public/index.html
142
+ - lib/public/js/angular-route.min.js
143
+ - lib/public/js/angular.js
144
+ - lib/public/js/app.js
170
145
  - lib/yopass.rb
171
146
  - lib/yopass/sms_provider.rb
172
147
  - lib/yopass/sms_provider/bulksms.rb
@@ -174,7 +149,6 @@ files:
174
149
  - spec/sms_provder_spec.rb
175
150
  - spec/spec_helper.rb
176
151
  - spec/yopass_spec.rb
177
- - yopass.god
178
152
  homepage: https://github.com/jhaals/yopass
179
153
  licenses:
180
154
  - Apache 2.0
@@ -183,7 +157,6 @@ post_install_message:
183
157
  rdoc_options: []
184
158
  require_paths:
185
159
  - lib
186
- - conf
187
160
  required_ruby_version: !ruby/object:Gem::Requirement
188
161
  requirements:
189
162
  - - ">="
data/CHANGELOG.md DELETED
@@ -1,39 +0,0 @@
1
- # Yopass changelog
2
-
3
- ### 2.2.0 - 2014-08-30
4
-
5
- - rate limiting - Secrets will be deleted after 3 failed attempts
6
- - fix issues building the docker container
7
-
8
- ### 2.1.1
9
-
10
- - fix missconfigured template rendering when sending decryption key over SMS
11
-
12
- ### 2.1.0
13
-
14
- - remove /get part from URLs
15
- - copy to clipboard for URLs
16
-
17
- ### 2.0.0
18
-
19
- - Rename `http_base_url` to base_url
20
- - Move configuration settings to environment variables
21
- - Use thin as webserver
22
- - Bump rspec version
23
- - Drop ruby 1.8.7 support
24
-
25
- ### 1.1.5
26
- - Ability to configure secret_max_length in yopass.yaml
27
-
28
- ### 1.1.4
29
- - remove gui messup
30
-
31
- ### 1.1.3
32
-
33
- - display placeholder for mobile number in form.
34
- - fixes bug where test would fail is memcached was running.
35
-
36
- ### 1.1.2
37
-
38
- - Typo
39
- - Shipp all fonts instead of loading them from external site. Caused insecure content warning
data/Procfile DELETED
@@ -1 +0,0 @@
1
- web: bundle exec rackup config.ru -p 4567 -s thin -o 0.0.0.0
data/conf/config.ru DELETED
@@ -1,3 +0,0 @@
1
- require 'rubygems'
2
- require 'yopass'
3
- run Yopass
data/conf/yopass.yaml DELETED
@@ -1,10 +0,0 @@
1
- memcached_url: 'localhost:11211'
2
- base_url: 'http://127.0.0.1:4567'
3
- secret_max_length: 100000
4
- send_sms: false
5
-
6
- sms::provider: 'bulksms'
7
- sms::settings:
8
- username: 'username'
9
- password: 'fancypass'
10
- sender: 'YoPass'
Binary file