htauth 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -41,8 +41,8 @@ describe HTAuth::CLI::Passwd do
41
41
  begin
42
42
  @htauth.run([ "-h" ])
43
43
  rescue SystemExit => se
44
- se.status.must_equal 1
45
- @stdout.string.must_match( /passwordfile username/m )
44
+ _(se.status).must_equal 1
45
+ _(@stdout.string).must_match( /passwordfile username/m )
46
46
  end
47
47
  end
48
48
 
@@ -50,8 +50,8 @@ describe HTAuth::CLI::Passwd do
50
50
  begin
51
51
  @htauth.run([ "--version" ])
52
52
  rescue SystemExit => se
53
- se.status.must_equal 1
54
- @stdout.string.must_match( /version #{HTAuth::VERSION}/)
53
+ _(se.status).must_equal 1
54
+ _(@stdout.string).must_match( /version #{HTAuth::VERSION}/)
55
55
  end
56
56
  end
57
57
 
@@ -62,11 +62,100 @@ describe HTAuth::CLI::Passwd do
62
62
  @stdin.rewind
63
63
  @htauth.run([ "-m", "-c", @new_file, "alice" ])
64
64
  rescue SystemExit => se
65
- se.status.must_equal 0
65
+ _(se.status).must_equal 0
66
66
  l = IO.readlines(@new_file)
67
67
  fields = l.first.split(':')
68
- fields.first.must_equal "alice"
69
- fields.last.must_match( /^\$apr1\$/ )
68
+ _(fields.first).must_equal "alice"
69
+ _(fields.last).must_match( /^\$apr1\$/ )
70
+ end
71
+ end
72
+
73
+ it "creates a new file with one bcrypt entry" do
74
+ begin
75
+ @stdin.puts "b secret"
76
+ @stdin.puts "b secret"
77
+ @stdin.rewind
78
+ @htauth.run([ "-B", "-c", @new_file, "brenda" ])
79
+ rescue SystemExit => se
80
+ _(se.status).must_equal 0
81
+ l = IO.readlines(@new_file)
82
+ fields = l.first.split(':')
83
+ _(fields.first).must_equal "brenda"
84
+ bcrypt_hash = fields.last
85
+
86
+ _(::BCrypt::Password.valid_hash?(bcrypt_hash)).wont_be_nil
87
+ end
88
+ end
89
+
90
+ it "allows the bcrypt cost to be set" do
91
+ begin
92
+ cost = 12
93
+ @stdin.puts "b secret"
94
+ @stdin.puts "b secret"
95
+ @stdin.rewind
96
+ @htauth.run([ "-C", "#{cost}", "-B", "-c", @new_file, "brenda" ])
97
+ rescue SystemExit => se
98
+ _(se.status).must_equal 0
99
+ l = IO.readlines(@new_file)
100
+ fields = l.first.split(':')
101
+ _(fields.first).must_equal "brenda"
102
+ bcrypt_hash = fields.last
103
+ _(::BCrypt::Password.valid_hash?(bcrypt_hash)).wont_be_nil
104
+
105
+ _, _version, count, _rest = bcrypt_hash.split("$")
106
+ _(count).must_equal ("%02d" % cost)
107
+ end
108
+ end
109
+
110
+ it "raises an error if the bcrypt cost is out of range" do
111
+ begin
112
+ @stdin.puts "b secret"
113
+ @stdin.puts "b secret"
114
+ @stdin.rewind
115
+ @htauth.run([ "-C", "42", "-B", "-c", @new_file, "brenda" ])
116
+ rescue SystemExit => se
117
+ _(@stderr.string).must_match( /ERROR:/m )
118
+ _(se.status).must_equal 1
119
+ end
120
+ end
121
+
122
+ it "raises an error if the bcrypt cost is not an integer" do
123
+ begin
124
+ @stdin.puts "b secret"
125
+ @stdin.puts "b secret"
126
+ @stdin.rewind
127
+ @htauth.run([ "-C", "forty-two", "-B", "-c", @new_file, "brenda" ])
128
+ rescue SystemExit => se
129
+ _(@stderr.string).must_match( /ERROR:/m )
130
+ _(se.status).must_equal 1
131
+ end
132
+
133
+ end
134
+
135
+ it "does not verify the password from stdin on -i option" do
136
+ begin
137
+ @stdin.puts "b secret"
138
+ @stdin.rewind
139
+ @htauth.run([ "-i", "-B", "-c", @new_file, "brenda" ])
140
+ rescue SystemExit => se
141
+ _(se.status).must_equal 0
142
+ l = IO.readlines(@new_file)
143
+ fields = l.first.split(':')
144
+ _(fields.first).must_equal "brenda"
145
+ bcrypt_hash = fields.last
146
+
147
+ _(::BCrypt::Password.valid_hash?(bcrypt_hash)).wont_be_nil
148
+ end
149
+ end
150
+
151
+ it "does not allow options -i and -b to both be set" do
152
+ begin
153
+ @stdin.puts "b secret"
154
+ @stdin.rewind
155
+ @htauth.run([ "-i", "-b", "-B", "-c", @new_file, "brenda", "b-secret" ])
156
+ rescue SystemExit => se
157
+ _(@stderr.string).must_match( /ERROR:/m )
158
+ _(se.status).must_equal 1
70
159
  end
71
160
  end
72
161
 
@@ -78,10 +167,10 @@ describe HTAuth::CLI::Passwd do
78
167
  @stdin.rewind
79
168
  @htauth.run([ "-c", @tf.path, "bob"])
80
169
  rescue SystemExit => se
81
- se.status.must_equal 0
170
+ _(se.status).must_equal 0
82
171
  after_lines = IO.readlines(@tf.path)
83
- after_lines.size.must_equal 1
84
- before_lines.size.must_equal 2
172
+ _(after_lines.size).must_equal 1
173
+ _(before_lines.size).must_equal 2
85
174
  end
86
175
  end
87
176
 
@@ -92,12 +181,12 @@ describe HTAuth::CLI::Passwd do
92
181
  @stdin.rewind
93
182
  @htauth.run([ "-s", @tf.path, "charlie" ])
94
183
  rescue SystemExit => se
95
- se.status.must_equal 0
184
+ _(se.status).must_equal 0
96
185
  after_lines = IO.readlines(@tf.path)
97
- after_lines.size.must_equal 3
186
+ _(after_lines.size).must_equal 3
98
187
  al = after_lines.last.split(':')
99
- al.first.must_equal "charlie"
100
- al.last.must_match( /\{SHA\}/ )
188
+ _(al.first).must_equal "charlie"
189
+ _(al.last).must_match( /\{SHA\}/ )
101
190
  end
102
191
  end
103
192
 
@@ -108,8 +197,8 @@ describe HTAuth::CLI::Passwd do
108
197
  @stdin.rewind
109
198
  @htauth.run(["-c", "-p", @tf.path, "bradley"])
110
199
  rescue SystemExit => se
111
- se.status.must_equal 0
112
- IO.read(@tf.path).strip.must_equal "bradley:a bad password"
200
+ _(se.status).must_equal 0
201
+ _(IO.read(@tf.path).strip).must_equal "bradley:a bad password"
113
202
  end
114
203
  end
115
204
 
@@ -117,8 +206,8 @@ describe HTAuth::CLI::Passwd do
117
206
  begin
118
207
  @htauth.run(["-c", "-p", "-b", @tf.path, "bradley", "a bad password"])
119
208
  rescue SystemExit => se
120
- se.status.must_equal 0
121
- IO.read(@tf.path).strip.must_equal "bradley:a bad password"
209
+ _(se.status).must_equal 0
210
+ _(IO.read(@tf.path).strip).must_equal "bradley:a bad password"
122
211
  end
123
212
  end
124
213
 
@@ -130,16 +219,16 @@ describe HTAuth::CLI::Passwd do
130
219
  @stdin.rewind
131
220
  @htauth.run([ "-d", @tf.path, "alice" ])
132
221
  rescue SystemExit => se
133
- @stderr.string.must_equal ""
134
- se.status.must_equal 0
222
+ _(@stderr.string).must_equal ""
223
+ _(se.status).must_equal 0
135
224
  after_lines = IO.readlines(@tf.path)
136
- after_lines.size.must_equal before_lines.size
225
+ _(after_lines.size).must_equal before_lines.size
137
226
 
138
227
  a_b = before_lines.first.split(":")
139
228
  a_a = after_lines.first.split(":")
140
229
 
141
- a_b.first.must_equal a_a.first
142
- a_b.last.wont_equal a_a.last
230
+ _(a_b.first).must_equal a_a.first
231
+ _(a_b.last).wont_equal a_a.last
143
232
  end
144
233
  end
145
234
 
@@ -147,9 +236,9 @@ describe HTAuth::CLI::Passwd do
147
236
  begin
148
237
  @htauth.run([ "-D", @tf.path, "bob" ])
149
238
  rescue SystemExit => se
150
- @stderr.string.must_equal ""
151
- se.status.must_equal 0
152
- IO.read(@tf.path).must_equal IO.read(PASSWD_DELETE_TEST_FILE)
239
+ _(@stderr.string).must_equal ""
240
+ _(se.status).must_equal 0
241
+ _(IO.read(@tf.path)).must_equal IO.read(PASSWD_DELETE_TEST_FILE)
153
242
  end
154
243
  end
155
244
 
@@ -157,8 +246,26 @@ describe HTAuth::CLI::Passwd do
157
246
  begin
158
247
  @htauth.run(["-n", "-p", "-b", "bradley", "a bad password"])
159
248
  rescue SystemExit => se
160
- se.status.must_equal 0
161
- @stdout.string.strip.must_equal "bradley:a bad password"
249
+ _(se.status).must_equal 0
250
+ _(@stdout.string.strip).must_equal "bradley:a bad password"
251
+ end
252
+ end
253
+
254
+ it "verifies a password when --verify is used - valid" do
255
+ begin
256
+ @htauth.run(["--verify", "-b", @tf.path, "alice", "a secret"])
257
+ rescue SystemExit => se
258
+ _(@stderr.string.strip).must_equal "Password for user alice correct."
259
+ _(se.status).must_equal 0
260
+ end
261
+ end
262
+
263
+ it "verifies a password when --verify is used - invalid" do
264
+ begin
265
+ @htauth.run(["--verify", "-b", @tf.path, "alice", "the wrong secret"])
266
+ rescue SystemExit => se
267
+ _(@stderr.string.strip).must_equal "Password verification for user alice failed."
268
+ _(se.status).must_equal 1
162
269
  end
163
270
  end
164
271
 
@@ -169,8 +276,8 @@ describe HTAuth::CLI::Passwd do
169
276
  @stdin.rewind
170
277
  @htauth.run([ "-c", "/etc/you-cannot-create-me", "alice"])
171
278
  rescue SystemExit => se
172
- @stderr.string.must_match( %r{Password file failure \(/etc/you-cannot-create-me\)}m )
173
- se.status.must_equal 1
279
+ _(@stderr.string).must_match( %r{Password file failure \(/etc/you-cannot-create-me\)}m )
280
+ _(se.status).must_equal 1
174
281
  end
175
282
  end
176
283
 
@@ -181,8 +288,8 @@ describe HTAuth::CLI::Passwd do
181
288
  @stdin.rewind
182
289
  @htauth.run([ @tf.path, "alice"])
183
290
  rescue SystemExit => se
184
- @stderr.string.must_match( /They don't match, sorry./m )
185
- se.status.must_equal 1
291
+ _(@stderr.string).must_match( /They don't match, sorry./m )
292
+ _(se.status).must_equal 1
186
293
  end
187
294
  end
188
295
 
@@ -190,8 +297,8 @@ describe HTAuth::CLI::Passwd do
190
297
  begin
191
298
  @htauth.run(["--blah"])
192
299
  rescue SystemExit => se
193
- @stderr.string.must_match( /ERROR:/m )
194
- se.status.must_equal 1
300
+ _(@stderr.string).must_match( /ERROR:/m )
301
+ _(se.status).must_equal 1
195
302
  end
196
303
  end
197
304
 
@@ -199,8 +306,25 @@ describe HTAuth::CLI::Passwd do
199
306
  begin
200
307
  @htauth.run(["-c", "-n"])
201
308
  rescue SystemExit => se
202
- @stderr.string.must_match( /ERROR:/m )
203
- se.status.must_equal 1
309
+ _(@stderr.string).must_match( /ERROR:/m )
310
+ _(se.status).must_equal 1
311
+ end
312
+ end
313
+
314
+ it "errors if multiple types of operations are attmpted to be used at once" do
315
+ begin
316
+ @htauth.run(["-n", "-D"])
317
+ rescue SystemExit => se
318
+ _(@stderr.string).must_match( /ERROR:/m )
319
+ _(se.status).must_equal 1
320
+ end
321
+
322
+ begin
323
+ @htauth.run(["--verify", "-D"])
324
+ rescue SystemExit => se
325
+ _(@stderr.string).must_match( /ERROR:/m )
326
+ _(se.status).must_equal 1
204
327
  end
328
+
205
329
  end
206
330
  end
@@ -2,15 +2,11 @@ require 'spec_helper'
2
2
  require 'htauth/crypt'
3
3
 
4
4
  describe HTAuth::Crypt do
5
- it "has a prefix" do
6
- HTAuth::Crypt.new.prefix.must_equal ""
7
- end
8
-
9
5
  it "encrypts the same way that apache does" do
10
6
  apache_salt = "L0LDd/.."
11
7
  apache_result = "L0ekWYm59LT1M"
12
8
  crypt = HTAuth::Crypt.new({ :salt => apache_salt} )
13
- crypt.encode("a secret").must_equal apache_result
9
+ _(crypt.encode("a secret")).must_equal apache_result
14
10
  end
15
11
  end
16
12
 
@@ -8,53 +8,53 @@ describe HTAuth::DigestEntry do
8
8
  end
9
9
 
10
10
  it "initializes with a user and realm" do
11
- @alice.user.must_equal "alice"
12
- @alice.realm.must_equal "htauth"
11
+ _(@alice.user).must_equal "alice"
12
+ _(@alice.realm).must_equal "htauth"
13
13
  end
14
14
 
15
15
  it "has the correct digest for a password" do
16
16
  @alice.password = "digit"
17
- @alice.digest.must_equal "4ed9e5744c6747af8f292d28afd6372e"
17
+ _(@alice.digest).must_equal "4ed9e5744c6747af8f292d28afd6372e"
18
18
  end
19
19
 
20
20
  it "returns username:realm for a key" do
21
- @alice.key.must_equal "alice:htauth"
21
+ _(@alice.key).must_equal "alice:htauth"
22
22
  end
23
23
 
24
24
  it "checks the password correctly" do
25
- @bob.authenticated?("b secret").must_equal true
25
+ _(@bob.authenticated?("b secret")).must_equal true
26
26
  end
27
27
 
28
28
  it "formats correctly when put to a string" do
29
- @bob.to_s.must_equal "bob:htauth:fcbeab6821d2ab3b00934c958db0fd1e"
29
+ _(@bob.to_s).must_equal "bob:htauth:fcbeab6821d2ab3b00934c958db0fd1e"
30
30
  end
31
31
 
32
32
  it "parses an input line" do
33
33
  @bob_new = HTAuth::DigestEntry.from_line("bob:htauth:fcbeab6821d2ab3b00934c958db0fd1e")
34
- @bob.user.must_equal @bob_new.user
35
- @bob.digest.must_equal @bob_new.digest
36
- @bob.realm.must_equal @bob_new.realm
34
+ _(@bob.user).must_equal @bob_new.user
35
+ _(@bob.digest).must_equal @bob_new.digest
36
+ _(@bob.realm).must_equal @bob_new.realm
37
37
  end
38
38
 
39
39
  it "knows if an input line is a possible entry and raises an exception" do
40
- lambda { HTAuth::DigestEntry.is_entry!("#stuff") }.must_raise(HTAuth::InvalidDigestEntry)
41
- lambda { HTAuth::DigestEntry.is_entry!("this:that:other:stuff") }.must_raise(HTAuth::InvalidDigestEntry)
42
- lambda { HTAuth::DigestEntry.is_entry!("this:that:other") }.must_raise(HTAuth::InvalidDigestEntry)
43
- lambda { HTAuth::DigestEntry.is_entry!("this:that:0a90549e8ffb2dd62f98252a95d88xyz") }.must_raise(HTAuth::InvalidDigestEntry)
40
+ _ { HTAuth::DigestEntry.is_entry!("#stuff") }.must_raise(HTAuth::InvalidDigestEntry)
41
+ _ { HTAuth::DigestEntry.is_entry!("this:that:other:stuff") }.must_raise(HTAuth::InvalidDigestEntry)
42
+ _ { HTAuth::DigestEntry.is_entry!("this:that:other") }.must_raise(HTAuth::InvalidDigestEntry)
43
+ _ { HTAuth::DigestEntry.is_entry!("this:that:0a90549e8ffb2dd62f98252a95d88xyz") }.must_raise(HTAuth::InvalidDigestEntry)
44
44
  end
45
45
 
46
46
  it "knows if an input line is a possible entry and returns false" do
47
- HTAuth::DigestEntry.is_entry?("#stuff").must_equal false
48
- HTAuth::DigestEntry.is_entry?("this:that:other:stuff").must_equal false
49
- HTAuth::DigestEntry.is_entry?("this:that:other").must_equal false
50
- HTAuth::DigestEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz").must_equal false
47
+ _(HTAuth::DigestEntry.is_entry?("#stuff")).must_equal false
48
+ _(HTAuth::DigestEntry.is_entry?("this:that:other:stuff")).must_equal false
49
+ _(HTAuth::DigestEntry.is_entry?("this:that:other")).must_equal false
50
+ _(HTAuth::DigestEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz")).must_equal false
51
51
  end
52
52
 
53
53
  it "knows if an input line is a possible entry and returns true" do
54
- HTAuth::DigestEntry.is_entry?("bob:htauth:0a90549e8ffb2dd62f98252a95d88697").must_equal true
54
+ _(HTAuth::DigestEntry.is_entry?("bob:htauth:0a90549e8ffb2dd62f98252a95d88697")).must_equal true
55
55
  end
56
56
 
57
57
  it "duplicates itself" do
58
- @alice.dup.to_s.must_equal @alice.to_s
58
+ _(@alice.dup.to_s).must_equal @alice.to_s
59
59
  end
60
60
  end
@@ -22,35 +22,35 @@ describe HTAuth::DigestFile do
22
22
 
23
23
  it "can add a new entry to an already existing digest file" do
24
24
  @digest_file.add_or_update("charlie", "htauth-new", "c secret")
25
- @digest_file.contents.must_equal IO.read(DIGEST_ADD_TEST_FILE)
25
+ _(@digest_file.contents).must_equal IO.read(DIGEST_ADD_TEST_FILE)
26
26
  end
27
27
 
28
28
  it "can tell if an entry already exists in the digest file" do
29
- @digest_file.has_entry?("alice", "htauth").must_equal true
30
- @digest_file.has_entry?("alice", "some other realm").must_equal false
29
+ _(@digest_file.has_entry?("alice", "htauth")).must_equal true
30
+ _(@digest_file.has_entry?("alice", "some other realm")).must_equal false
31
31
  end
32
32
 
33
33
  it "can update an entry in an already existing digest file" do
34
34
  @digest_file.add_or_update("alice", "htauth", "a new secret")
35
- @digest_file.contents.must_equal IO.read(DIGEST_UPDATE_TEST_FILE)
35
+ _(@digest_file.contents).must_equal IO.read(DIGEST_UPDATE_TEST_FILE)
36
36
  end
37
37
 
38
38
  it "fetches a copy of an entry" do
39
- @digest_file.fetch("alice", "htauth").to_s.must_equal "alice:htauth:2f361db93147d84831eb34f19d05bfbb"
39
+ _(@digest_file.fetch("alice", "htauth").to_s).must_equal "alice:htauth:2f361db93147d84831eb34f19d05bfbb"
40
40
  end
41
41
 
42
42
  it "raises an error if an attempt is made to alter a non-existenet file" do
43
- lambda { HTAuth::DigestFile.new("some-file") }.must_raise(HTAuth::FileAccessError)
43
+ _ { HTAuth::DigestFile.new("some-file") }.must_raise(HTAuth::FileAccessError)
44
44
  end
45
45
 
46
46
  # this test will only work on systems that have /etc/ssh_host_rsa_key
47
47
  it "raises an error if an attempt is made to open a file where no permissions are granted" do
48
- lambda { HTAuth::DigestFile.new("/etc/ssh_host_rsa_key") }.must_raise(HTAuth::FileAccessError)
48
+ _ { HTAuth::DigestFile.new("/etc/ssh_host_rsa_key") }.must_raise(HTAuth::FileAccessError)
49
49
  end
50
50
 
51
51
  it "deletes an entry" do
52
52
  @digest_file.delete("alice", "htauth")
53
- @digest_file.contents.must_equal IO.read(DIGEST_DELETE_TEST_FILE)
53
+ _(@digest_file.contents).must_equal IO.read(DIGEST_DELETE_TEST_FILE)
54
54
  end
55
55
 
56
56
  it "is usable in a ruby manner and yeilds itself when opened" do
@@ -59,7 +59,7 @@ describe HTAuth::DigestFile do
59
59
  pf.delete('bob', 'htauth')
60
60
  end
61
61
  lines = IO.readlines(@tf.path)
62
- lines.size.must_equal 1
63
- lines.first.strip.must_equal "alice:htauth:2f361db93147d84831eb34f19d05bfbb"
62
+ _(lines.size).must_equal 1
63
+ _(lines.first.strip).must_equal "alice:htauth:2f361db93147d84831eb34f19d05bfbb"
64
64
  end
65
65
  end
@@ -3,15 +3,11 @@ require File.join(File.dirname(__FILE__),"spec_helper.rb")
3
3
  require 'htauth/md5'
4
4
 
5
5
  describe HTAuth::Md5 do
6
- it "has a prefix" do
7
- HTAuth::Md5.new.prefix.must_equal "$apr1$"
8
- end
9
-
10
6
  it "encrypts the same way that apache does" do
11
7
  apache_salt = "L0LDd/.."
12
8
  apache_result = "$apr1$L0LDd/..$yhUzDjpxam5F1kWdtwMco1"
13
9
  md5 = HTAuth::Md5.new({ 'salt' => apache_salt })
14
- md5.encode("a secret").must_equal apache_result
10
+ _(md5.encode("a secret")).must_equal apache_result
15
11
  end
16
12
  end
17
13