yak 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -0
- data/Manifest.txt +1 -0
- data/README.txt +12 -10
- data/lib/yak.rb +124 -25
- data/script/yak_completion +44 -0
- 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
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
|
47
|
-
>>
|
48
|
-
#
|
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
|
60
|
+
Listing keys:
|
59
61
|
$ yak --list
|
60
62
|
# returns all saved pairs
|
61
63
|
|
62
64
|
$ yak --list key
|
63
|
-
# returns all
|
65
|
+
# returns all keys matching /key/
|
64
66
|
|
65
67
|
$ yak --list ^key$
|
66
|
-
# returns unique
|
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
|
-
|
31
|
+
# Version of Yak.
|
32
|
+
VERSION = "1.0.4"
|
29
33
|
|
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
|
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 "
|
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
|
-
|
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}
|
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
|
-
|
166
|
-
when /
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
18
|
-
|
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
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
25
34
|
- !ruby/object:Gem::Dependency
|
26
35
|
name: session
|
27
|
-
|
28
|
-
|
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
|
-
|
35
|
-
|
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
|
-
|
58
|
-
|
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
|
-
|
64
|
-
|
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.
|
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
|