yak 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/History.txt +14 -0
  2. data/Manifest.txt +1 -0
  3. data/README.txt +12 -10
  4. data/lib/yak.rb +124 -25
  5. data/script/yak_completion +44 -0
  6. metadata +38 -38
data/History.txt CHANGED
@@ -1,3 +1,17 @@
1
+ === 1.0.4 / 2010-02-23
2
+
3
+ * Enhancemennts:
4
+
5
+ * Added support for bash completion
6
+
7
+ * Bugfixes:
8
+
9
+ * Fixed CipherError namespace change for different Ruby versions
10
+
11
+ * List option now only returns keys
12
+
13
+ * Rdoc README processing error fixed
14
+
1
15
  === 1.0.3 / 2010-02-22
2
16
 
3
17
  * Enhancements:
data/Manifest.txt CHANGED
@@ -1,5 +1,6 @@
1
1
  bin/yak
2
2
  lib/yak.rb
3
+ script/yak_completion
3
4
  History.txt
4
5
  Manifest.txt
5
6
  Rakefile
data/README.txt CHANGED
@@ -1,5 +1,7 @@
1
1
  = Yak
2
2
 
3
+ http://github.com/yaksnrainbows/yak
4
+
3
5
  == Description
4
6
 
5
7
  Yak is a simple command line app to store and retrieve passwords securely
@@ -13,17 +15,17 @@ Config can be set in ~/.yakrc.
13
15
 
14
16
  Session is the length of time in seconds that Yak will remember the
15
17
  master password:
16
- :session: 30
18
+ :session : 30
17
19
 
18
20
  If using sessions is not desired and you want to enter the
19
21
  master password every time, set:
20
- :session: false
22
+ :session : false
21
23
 
22
24
  Always set the password by default, use:
23
- :password: plain_text_password
25
+ :password : plain_text_password
24
26
 
25
27
  Turn off password confirmation prompts when a new password is entered:
26
- :confirm_prompt: false
28
+ :confirm_prompt : false
27
29
 
28
30
 
29
31
  == Usage
@@ -43,9 +45,9 @@ Retrieving a saved password:
43
45
  $ yak gmail
44
46
  # copies the gmail password to the clipboard
45
47
 
46
- $ yak --list gmail
47
- >> gmail: my_password
48
- # matches all password keys to /gmail/ and outputs to stdout
48
+ $ yak -p gmail
49
+ >> my_password
50
+ # outputs gmail password to stdout
49
51
 
50
52
  Removing a stored password:
51
53
  $ yak -r gmail
@@ -55,12 +57,12 @@ Changing the master password:
55
57
  $ yak -n
56
58
  # prompts for old password first, then the new password
57
59
 
58
- Listing key/password pairs:
60
+ Listing keys:
59
61
  $ yak --list
60
62
  # returns all saved pairs
61
63
 
62
64
  $ yak --list key
63
- # returns all saved pairs with a key matching /key/
65
+ # returns all keys matching /key/
64
66
 
65
67
  $ yak --list ^key$
66
- # returns unique saved pair with a key matching /^key$/
68
+ # returns unique key matching /^key$/
data/lib/yak.rb CHANGED
@@ -22,12 +22,20 @@ require 'session'
22
22
  # :confirm_prompt: false
23
23
  # To set the path to the yak data file:
24
24
  # :data_file: /path/to/file
25
+ # Using bash completion for stored keys:
26
+ # :bash_completion: true #=> completion only available during session
27
+ # :bash_completion: :always #=> completion always available
25
28
 
26
29
  class Yak
27
30
 
28
- VERSION = "1.0.3"
31
+ # Version of Yak.
32
+ VERSION = "1.0.4"
29
33
 
30
- DEFAULT_CONFIG = {:session => 30}
34
+ # Default config used.
35
+ DEFAULT_CONFIG = {:session => 30, :bash_completion => true}
36
+
37
+ # Different versions of ruby have a different namespace for CipherError
38
+ CIPHER_ERROR = OpenSSL::Cipher::CipherError rescue OpenSSL::CipherError
31
39
 
32
40
  ##
33
41
  # Run Yak with argv:
@@ -46,14 +54,14 @@ class Yak
46
54
 
47
55
  yak = new user, config
48
56
 
49
- yak.connect_data
50
57
  yak.start_session
58
+ yak.connect_data
51
59
 
52
60
  args = [options[:action], yak, options[:key], options[:value]].compact
53
61
 
54
62
  self.send(*args)
55
63
 
56
- rescue OpenSSL::Cipher::CipherError => e
64
+ rescue CIPHER_ERROR => e
57
65
  $stderr << "Bad password.\n"
58
66
  exit 1
59
67
  end
@@ -68,8 +76,42 @@ class Yak
68
76
  return if File.file? user_config_file
69
77
 
70
78
  hl = HighLine.new $stdin, $stderr
71
- hl.say "Thanks for installing Yak!"
79
+ hl.say "\n\nThanks for installing Yak!\n\n"
80
+
81
+ setup_bash_completion
82
+
83
+ data_file = prompt_data_loc user, hl
84
+
85
+ new_config = DEFAULT_CONFIG.merge(:data_file => data_file)
86
+
87
+ make_config_file user, new_config
88
+ end
89
+
90
+
91
+ ##
92
+ # Check and setup bash completion.
93
+
94
+ def self.setup_bash_completion
95
+ completion_dir = "/etc/bash_completion.d"
96
+
97
+ completion_file = File.join File.dirname(__FILE__),
98
+ "../script/yak_completion"
99
+ completion_file = File.expand_path completion_file
100
+
101
+ if File.directory? completion_dir
102
+ FileUtils.cp completion_file, File.join(completion_dir, ".")
103
+ else
104
+ $stderr << "\nError: Could not find directory #{completion_dir}\n"
105
+ $stderr << "If you would like to use yak's bash completion, "
106
+ $stderr << "make sure to source #{completion_file} in .bashrc\n\n"
107
+ end
108
+ end
109
+
72
110
 
111
+ ##
112
+ # Prompt the user for the location of the data file.
113
+
114
+ def self.prompt_data_loc user, hl
73
115
  data_file_opts = []
74
116
 
75
117
  usrhome = File.expand_path "~#{user}/"
@@ -86,10 +128,7 @@ class Yak
86
128
  end
87
129
  end
88
130
 
89
- data_file = File.join data_path, ".yakdata"
90
- new_config = DEFAULT_CONFIG.merge(:data_file => data_file)
91
-
92
- make_config_file user, new_config
131
+ File.join data_path, ".yakdata"
93
132
  end
94
133
 
95
134
 
@@ -112,46 +151,68 @@ class Yak
112
151
 
113
152
  File.open(user_config_file, "w+"){|f| f.write config_str }
114
153
  $stderr << "Created Yak config file #{user_config_file}:\n"
115
- $stderr << "#{config_str}\n"
154
+ $stderr << "#{config_str}---\n\n"
116
155
  end
117
156
 
118
157
 
158
+ ##
159
+ # Remove a key/value pair from a yak instance.
160
+
119
161
  def self.remove yak, name
120
162
  yak.remove name
121
163
  yak.write_data
122
164
  end
123
165
 
124
166
 
167
+ ##
168
+ # Add a key/value pair to a yak instance.
169
+
125
170
  def self.store yak, name, value=nil
126
171
  yak.store name, value
127
172
  yak.write_data
128
173
  end
129
174
 
130
175
 
176
+ ##
177
+ # Get a password value from a yak instance and copy it to the clipboard.
178
+
131
179
  def self.retrieve yak, name
132
180
  send_to_clipboard yak.retrieve(name)
133
181
  end
134
182
 
135
183
 
184
+ ##
185
+ # Get a password value from a yak instance and output it to the stdout.
186
+
136
187
  def self.print_password yak, name
137
188
  $stdout << "#{yak.retrieve(name)}\n"
138
189
  end
139
190
 
140
191
 
192
+ ##
193
+ # Delete the data file of a yak instance after confirming with the user.
194
+
141
195
  def self.delete_data yak
142
196
  yak.delete_data_file! true
143
197
  end
144
198
 
145
199
 
200
+ ##
201
+ # List matched keys of a yak instance.
202
+
146
203
  def self.list yak, name=nil
147
204
  key_regex = /#{name || ".+"}/
148
205
 
149
206
  yak.data.each do |key, value|
150
- $stdout << "#{key}: #{value}\n" if key =~ key_regex
207
+ $stdout << "#{key}\n" if key =~ key_regex
151
208
  end
152
209
  end
153
210
 
154
211
 
212
+ ##
213
+ # Assign a new master password to a yak instance.
214
+ # Prompts the user if no value is given.
215
+
155
216
  def self.new_password yak, value=nil
156
217
  yak.new_password value
157
218
  yak.write_data
@@ -159,30 +220,35 @@ class Yak
159
220
  end
160
221
 
161
222
 
223
+ ##
224
+ # Send the passed string to the keyboard.
225
+ # Only supports darwin (pbcopy), linux (xclip) and cygwin (putclip).
226
+
162
227
  def self.send_to_clipboard string
163
228
  copy_cmd = case RUBY_PLATFORM
164
- when /darwin/
165
- "echo -n \"#{string}\" | pbcopy"
166
- when /linux/
167
- "echo -n \"#{string}\" | xclip"
168
- when /cigwin/
169
- "echo -n \"#{string}\" | putclip"
170
- when /(win|mingw)/
171
- "echo \"#{string}\" | clip"
229
+ when /darwin/ then "pbcopy"
230
+ when /linux/ then "xclip"
231
+ when /cygwin/ then "putclip"
172
232
  else
173
233
  $stderr << "No clipboad cmd for platform #{RUBY_PLATFORM}\n"
174
234
  exit 1
175
235
  end
176
236
 
177
- Session::Bash.new.execute copy_cmd
237
+ Session::Bash.new.execute "echo -n \"#{string}\" | #{copy_cmd}"
178
238
  end
179
239
 
180
240
 
241
+ ##
242
+ # Get a user's yak config file. Typically ~user/.yakrc.
243
+
181
244
  def self.yak_config_file user
182
245
  File.expand_path "~#{user}/.yakrc"
183
246
  end
184
247
 
185
248
 
249
+ ##
250
+ # Parse ARGV data.
251
+
186
252
  def self.parse_args argv
187
253
  options = {}
188
254
 
@@ -192,7 +258,7 @@ class Yak
192
258
  opt.release = nil
193
259
 
194
260
  opt.banner = <<-EOF
195
- #{opt.program_name} is a simple app to store and retrieve passwords securely.
261
+ Yak is a simple app to store and retrieve passwords securely.
196
262
  Retrieved passwords get copied to the clipboard by default.
197
263
 
198
264
  Usage:
@@ -220,7 +286,7 @@ Retrieved passwords get copied to the clipboard by default.
220
286
  end
221
287
 
222
288
  opt.on('-l', '--list [REGEX]',
223
- 'List key/password pairs to the stdout') do |key|
289
+ 'List keys to the stdout') do |key|
224
290
  options[:action] = :list
225
291
  options[:key] = key
226
292
  end
@@ -257,7 +323,7 @@ Retrieved passwords get copied to the clipboard by default.
257
323
  end
258
324
 
259
325
 
260
- attr_reader :user, :data
326
+ attr_reader :user, :data, :use_completion
261
327
 
262
328
  ##
263
329
  # Create a new Yak instance for a given user:
@@ -280,6 +346,9 @@ Retrieved passwords get copied to the clipboard by default.
280
346
  @password_file = File.join @yak_dir, "password"
281
347
  @data_file = options[:data_file] || File.join(@yak_dir, "data")
282
348
 
349
+ @key_list_file = File.join @yak_dir, "keys"
350
+ @use_completion = options[:bash_completion]
351
+
283
352
  @session_pid = nil
284
353
  @session_pid = File.read(@pid_file).to_i if File.file? @pid_file
285
354
 
@@ -297,15 +366,17 @@ Retrieved passwords get copied to the clipboard by default.
297
366
  def start_session
298
367
  return unless @session_length
299
368
 
369
+ pswd = sha_password # Do stdio before writing to file!
370
+
300
371
  end_session if has_session?
301
372
 
302
373
  pid = fork do
303
374
  sleep @session_length
304
- FileUtils.rm_f [@password_file, @pid_file]
375
+ remove_session_files
305
376
  end
306
377
 
378
+ File.open(@password_file, "w+"){|f| f.write pswd }
307
379
  File.open(@pid_file, "w+"){|f| f.write pid }
308
- File.open(@password_file, "w+"){|f| f.write sha_password }
309
380
 
310
381
  Process.detach pid
311
382
  end
@@ -317,7 +388,16 @@ Retrieved passwords get copied to the clipboard by default.
317
388
  def end_session
318
389
  return unless @session_pid
319
390
  Process.kill 9, @session_pid rescue false
391
+ remove_session_files
392
+ end
393
+
394
+
395
+ ##
396
+ # Deletes files used during a session.
397
+
398
+ def remove_session_files
320
399
  FileUtils.rm_f [@password_file, @pid_file]
400
+ FileUtils.rm_f @key_list_file unless @use_completion == :always
321
401
  end
322
402
 
323
403
 
@@ -388,7 +468,11 @@ Retrieved passwords get copied to the clipboard by default.
388
468
  if data_file_exists?
389
469
  data = ""
390
470
  File.open(@data_file, "rb"){|f| data << f.read }
471
+
391
472
  @data = YAML.load decrypt(data)
473
+
474
+ write_key_list if @use_completion
475
+
392
476
  else
393
477
  @data = {}
394
478
  write_data
@@ -443,6 +527,16 @@ Retrieved passwords get copied to the clipboard by default.
443
527
  def write_data password=nil
444
528
  data = encrypt @data.to_yaml, password
445
529
  File.open(@data_file, "w+"){|f| f.write data}
530
+
531
+ write_key_list if @use_completion == :always
532
+ end
533
+
534
+
535
+ ##
536
+ # Write the key list file. Used for bash completion.
537
+
538
+ def write_key_list
539
+ File.open(@key_list_file, "w+"){|f| f.write @data.keys.join(" ") }
446
540
  end
447
541
 
448
542
 
@@ -478,6 +572,11 @@ Retrieved passwords get copied to the clipboard by default.
478
572
  end
479
573
 
480
574
 
575
+ ##
576
+ # Get the cypher output:
577
+ # get_cypher_out :encrypt, plain_string
578
+ # get_cypher_out :decrypt, encrypted_string
579
+
481
580
  def get_cypher_out method, string, password=nil
482
581
  password ||= sha_password
483
582
 
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+
3
+ _valid_yak_option()
4
+ {
5
+ local valid_prevs prevs_num curr_prev prev
6
+
7
+ prev="$1"
8
+
9
+ valid_prevs=( '-a' '--add' '-r' '--remove' '-l' '--list' '-p' '--print' 'yak' )
10
+ prevs_num=${#valid_prevs[@]}
11
+
12
+ for ((i=0;i<$prevs_num;i++)); do
13
+ curr_prev=${valid_prevs[${i}]}
14
+
15
+ if [ "$prev" == $curr_prev ]; then
16
+ echo "$prev"
17
+ return 0
18
+ fi
19
+ done
20
+
21
+ return 1
22
+ }
23
+
24
+ _yak()
25
+ {
26
+ local cur prev opts yak_keys
27
+ COMPREPLY=()
28
+ cur="${COMP_WORDS[COMP_CWORD]}"
29
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
30
+
31
+ yak_keys="$HOME/.yak/keys"
32
+
33
+
34
+ if [ -f "$yak_keys" ] && [ $(_valid_yak_option "$prev") ]; then
35
+ opts=$(cat $yak_keys)
36
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
37
+ return 0
38
+ fi
39
+
40
+ return 1
41
+ }
42
+
43
+ complete -F _yak yak
44
+
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yak
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 4
9
+ version: 1.0.4
5
10
  platform: ruby
6
11
  authors:
7
12
  - Jeremie Castagna
@@ -14,54 +19,46 @@ default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: highline
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 5
30
+ - 1
23
31
  version: 1.5.1
24
- version:
32
+ type: :runtime
33
+ version_requirements: *id001
25
34
  - !ruby/object:Gem::Dependency
26
35
  name: session
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
30
38
  requirements:
31
39
  - - ">="
32
40
  - !ruby/object:Gem::Version
41
+ segments:
42
+ - 2
43
+ - 4
44
+ - 0
33
45
  version: 2.4.0
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: rubyforge
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 2.0.3
44
- version:
45
- - !ruby/object:Gem::Dependency
46
- name: gemcutter
47
- type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: 0.3.0
54
- version:
46
+ type: :runtime
47
+ version_requirements: *id002
55
48
  - !ruby/object:Gem::Dependency
56
49
  name: hoe
57
- type: :development
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
60
52
  requirements:
61
53
  - - ">="
62
54
  - !ruby/object:Gem::Version
63
- version: 2.5.0
64
- version:
55
+ segments:
56
+ - 2
57
+ - 3
58
+ - 3
59
+ version: 2.3.3
60
+ type: :development
61
+ version_requirements: *id003
65
62
  description: |-
66
63
  Yak is a simple command line app to store and retrieve passwords securely
67
64
  under a master password, and allows one password repository per system user.
@@ -79,12 +76,13 @@ extra_rdoc_files:
79
76
  files:
80
77
  - bin/yak
81
78
  - lib/yak.rb
79
+ - script/yak_completion
82
80
  - History.txt
83
81
  - Manifest.txt
84
82
  - Rakefile
85
83
  - README.txt
86
84
  has_rdoc: true
87
- homepage:
85
+ homepage: http://github.com/yaksnrainbows/yak
88
86
  licenses: []
89
87
 
90
88
  post_install_message:
@@ -97,18 +95,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
95
  requirements:
98
96
  - - ">="
99
97
  - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
100
100
  version: "0"
101
- version:
102
101
  required_rubygems_version: !ruby/object:Gem::Requirement
103
102
  requirements:
104
103
  - - ">="
105
104
  - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
106
107
  version: "0"
107
- version:
108
108
  requirements: []
109
109
 
110
110
  rubyforge_project: yak
111
- rubygems_version: 1.3.5
111
+ rubygems_version: 1.3.6
112
112
  signing_key:
113
113
  specification_version: 3
114
114
  summary: Yak is a simple command line app to store and retrieve passwords securely under a master password, and allows one password repository per system user