htauth 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/CONTRIBUTING.md +46 -0
- data/HISTORY.md +36 -0
- data/Manifest.txt +45 -0
- data/{README → README.md} +21 -22
- data/Rakefile +17 -0
- data/bin/htpasswd-ruby +5 -5
- data/lib/htauth/algorithm.rb +1 -8
- data/lib/htauth/crypt.rb +1 -1
- data/lib/htauth/digest.rb +5 -2
- data/lib/htauth/digest_entry.rb +5 -4
- data/lib/htauth/digest_file.rb +1 -1
- data/lib/htauth/errors.rb +10 -0
- data/lib/htauth/file.rb +1 -1
- data/lib/htauth/md5.rb +2 -0
- data/lib/htauth/passwd.rb +10 -4
- data/lib/htauth/passwd_entry.rb +2 -1
- data/lib/htauth/passwd_file.rb +64 -63
- data/lib/htauth/plaintext.rb +12 -11
- data/lib/htauth/version.rb +8 -9
- data/lib/htauth.rb +14 -4
- data/spec/crypt_spec.rb +10 -12
- data/spec/digest_entry_spec.rb +20 -21
- data/spec/digest_file_spec.rb +11 -12
- data/spec/digest_spec.rb +23 -23
- data/spec/md5_spec.rb +2 -2
- data/spec/passwd_entry_spec.rb +47 -48
- data/spec/passwd_file_spec.rb +12 -13
- data/spec/passwd_spec.rb +37 -38
- data/spec/plaintext_spec.rb +4 -7
- data/spec/sha1_spec.rb +3 -5
- data/spec/spec_helper.rb +8 -4
- data/spec/test.add.digest +3 -0
- data/spec/test.add.passwd +3 -0
- data/spec/test.delete.digest +1 -0
- data/spec/test.delete.passwd +1 -0
- data/spec/test.original.digest +2 -0
- data/spec/test.original.passwd +2 -0
- data/spec/test.update.digest +2 -0
- data/spec/test.update.passwd +2 -0
- data/tasks/default.rake +276 -0
- data/tasks/this.rb +214 -0
- metadata +131 -75
- data/HISTORY +0 -26
- data/gemspec.rb +0 -43
- data/tasks/announce.rake +0 -38
- data/tasks/config.rb +0 -98
- data/tasks/distribution.rake +0 -46
- data/tasks/documentation.rake +0 -31
- data/tasks/rspec.rake +0 -29
- data/tasks/rubyforge.rake +0 -59
- data/tasks/utils.rb +0 -80
data/lib/htauth/version.rb
CHANGED
@@ -1,22 +1,21 @@
|
|
1
|
-
require 'htauth'
|
2
1
|
module HTAuth
|
2
|
+
VERSION = "1.1.0"
|
3
3
|
module Version
|
4
|
-
|
5
|
-
MINOR = 0
|
6
|
-
BUILD = 3
|
7
|
-
|
4
|
+
STRING = HTAuth::VERSION
|
8
5
|
def to_a
|
9
|
-
|
6
|
+
STRING.split(".")
|
10
7
|
end
|
11
8
|
|
12
9
|
def to_s
|
13
|
-
|
10
|
+
STRING
|
14
11
|
end
|
15
12
|
|
16
13
|
module_function :to_a
|
17
14
|
module_function :to_s
|
18
15
|
|
19
|
-
|
16
|
+
MAJOR = Version.to_a[0]
|
17
|
+
MINOR = Version.to_a[1]
|
18
|
+
BUILD = Version.to_a[2]
|
19
|
+
|
20
20
|
end
|
21
|
-
VERSION = Version.to_s
|
22
21
|
end
|
data/lib/htauth.rb
CHANGED
@@ -26,11 +26,21 @@ module HTAuth
|
|
26
26
|
sp = ::File.join( sp, *args ) if args
|
27
27
|
end
|
28
28
|
|
29
|
-
class FileAccessError < StandardError ; end
|
30
|
-
class TempFileError < StandardError ; end
|
31
|
-
class PasswordError < StandardError ; end
|
32
29
|
end
|
33
30
|
|
34
31
|
require 'htauth/version'
|
35
|
-
require 'htauth/
|
32
|
+
require 'htauth/algorithm'
|
33
|
+
require 'htauth/crypt'
|
36
34
|
require 'htauth/digest'
|
35
|
+
require 'htauth/digest_entry'
|
36
|
+
require 'htauth/digest_file'
|
37
|
+
require 'htauth/entry'
|
38
|
+
require 'htauth/errors'
|
39
|
+
require 'htauth/file'
|
40
|
+
require 'htauth/md5'
|
41
|
+
require 'htauth/passwd'
|
42
|
+
require 'htauth/passwd_entry'
|
43
|
+
require 'htauth/passwd_file'
|
44
|
+
require 'htauth/plaintext'
|
45
|
+
require 'htauth/sha1'
|
46
|
+
|
data/spec/crypt_spec.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
|
-
|
2
|
-
require File.join(File.dirname(__FILE__),"spec_helper.rb")
|
3
|
-
|
1
|
+
require 'spec_helper'
|
4
2
|
require 'htauth/crypt'
|
5
3
|
|
6
4
|
describe HTAuth::Crypt do
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
it "has a prefix" do
|
6
|
+
HTAuth::Crypt.new.prefix.must_equal ""
|
7
|
+
end
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
it "encrypts the same way that apache does" do
|
10
|
+
apache_salt = "L0LDd/.."
|
11
|
+
apache_result = "L0ekWYm59LT1M"
|
12
|
+
crypt = HTAuth::Crypt.new({ :salt => apache_salt} )
|
13
|
+
crypt.encode("a secret").must_equal apache_result
|
14
|
+
end
|
17
15
|
end
|
18
16
|
|
data/spec/digest_entry_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'htauth/digest_entry'
|
4
3
|
|
5
4
|
describe HTAuth::DigestEntry do
|
@@ -9,53 +8,53 @@ describe HTAuth::DigestEntry do
|
|
9
8
|
end
|
10
9
|
|
11
10
|
it "initializes with a user and realm" do
|
12
|
-
@alice.user.
|
13
|
-
@alice.realm.
|
11
|
+
@alice.user.must_equal "alice"
|
12
|
+
@alice.realm.must_equal "htauth"
|
14
13
|
end
|
15
14
|
|
16
15
|
it "has the correct digest for a password" do
|
17
16
|
@alice.password = "digit"
|
18
|
-
@alice.digest.
|
17
|
+
@alice.digest.must_equal "4ed9e5744c6747af8f292d28afd6372e"
|
19
18
|
end
|
20
19
|
|
21
20
|
it "returns username:realm for a key" do
|
22
|
-
@alice.key.
|
21
|
+
@alice.key.must_equal "alice:htauth"
|
23
22
|
end
|
24
23
|
|
25
24
|
it "checks the password correctly" do
|
26
|
-
@bob.authenticated?("b secret").
|
25
|
+
@bob.authenticated?("b secret").must_equal true
|
27
26
|
end
|
28
27
|
|
29
28
|
it "formats correctly when put to a string" do
|
30
|
-
@bob.to_s.
|
29
|
+
@bob.to_s.must_equal "bob:htauth:fcbeab6821d2ab3b00934c958db0fd1e"
|
31
30
|
end
|
32
31
|
|
33
32
|
it "parses an input line" do
|
34
33
|
@bob_new = HTAuth::DigestEntry.from_line("bob:htauth:fcbeab6821d2ab3b00934c958db0fd1e")
|
35
|
-
@bob.user.
|
36
|
-
@bob.digest.
|
37
|
-
@bob.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
|
38
37
|
end
|
39
38
|
|
40
39
|
it "knows if an input line is a possible entry and raises an exception" do
|
41
|
-
lambda { HTAuth::DigestEntry.is_entry!("#stuff") }.
|
42
|
-
lambda { HTAuth::DigestEntry.is_entry!("this:that:other:stuff") }.
|
43
|
-
lambda { HTAuth::DigestEntry.is_entry!("this:that:other") }.
|
44
|
-
lambda { HTAuth::DigestEntry.is_entry!("this:that:0a90549e8ffb2dd62f98252a95d88xyz") }.
|
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)
|
45
44
|
end
|
46
45
|
|
47
46
|
it "knows if an input line is a possible entry and returns false" do
|
48
|
-
HTAuth::DigestEntry.is_entry?("#stuff").
|
49
|
-
HTAuth::DigestEntry.is_entry?("this:that:other:stuff").
|
50
|
-
HTAuth::DigestEntry.is_entry?("this:that:other").
|
51
|
-
HTAuth::DigestEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz").
|
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
|
52
51
|
end
|
53
52
|
|
54
53
|
it "knows if an input line is a possible entry and returns true" do
|
55
|
-
HTAuth::DigestEntry.is_entry?("bob:htauth:0a90549e8ffb2dd62f98252a95d88697").
|
54
|
+
HTAuth::DigestEntry.is_entry?("bob:htauth:0a90549e8ffb2dd62f98252a95d88697").must_equal true
|
56
55
|
end
|
57
56
|
|
58
57
|
it "duplicates itself" do
|
59
|
-
@alice.dup.to_s.
|
58
|
+
@alice.dup.to_s.must_equal @alice.to_s
|
60
59
|
end
|
61
60
|
end
|
data/spec/digest_file_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'htauth/digest_file'
|
4
3
|
require 'tempfile'
|
5
4
|
|
@@ -23,35 +22,35 @@ describe HTAuth::DigestFile do
|
|
23
22
|
|
24
23
|
it "can add a new entry to an already existing digest file" do
|
25
24
|
@digest_file.add_or_update("charlie", "htauth-new", "c secret")
|
26
|
-
@digest_file.contents.
|
25
|
+
@digest_file.contents.must_equal IO.read(DIGEST_ADD_TEST_FILE)
|
27
26
|
end
|
28
27
|
|
29
28
|
it "can tell if an entry already exists in the digest file" do
|
30
|
-
@digest_file.has_entry?("alice", "htauth").
|
31
|
-
@digest_file.has_entry?("alice", "some other realm").
|
29
|
+
@digest_file.has_entry?("alice", "htauth").must_equal true
|
30
|
+
@digest_file.has_entry?("alice", "some other realm").must_equal false
|
32
31
|
end
|
33
32
|
|
34
33
|
it "can update an entry in an already existing digest file" do
|
35
34
|
@digest_file.add_or_update("alice", "htauth", "a new secret")
|
36
|
-
@digest_file.contents.
|
35
|
+
@digest_file.contents.must_equal IO.read(DIGEST_UPDATE_TEST_FILE)
|
37
36
|
end
|
38
37
|
|
39
38
|
it "fetches a copy of an entry" do
|
40
|
-
@digest_file.fetch("alice", "htauth").to_s.
|
39
|
+
@digest_file.fetch("alice", "htauth").to_s.must_equal "alice:htauth:2f361db93147d84831eb34f19d05bfbb"
|
41
40
|
end
|
42
41
|
|
43
42
|
it "raises an error if an attempt is made to alter a non-existenet file" do
|
44
|
-
lambda { HTAuth::DigestFile.new("some-file") }.
|
43
|
+
lambda { HTAuth::DigestFile.new("some-file") }.must_raise(HTAuth::FileAccessError)
|
45
44
|
end
|
46
45
|
|
47
46
|
# this test will only work on systems that have /etc/ssh_host_rsa_key
|
48
47
|
it "raises an error if an attempt is made to open a file where no permissions are granted" do
|
49
|
-
lambda { HTAuth::DigestFile.new("/etc/ssh_host_rsa_key") }.
|
48
|
+
lambda { HTAuth::DigestFile.new("/etc/ssh_host_rsa_key") }.must_raise(HTAuth::FileAccessError)
|
50
49
|
end
|
51
50
|
|
52
51
|
it "deletes an entry" do
|
53
52
|
@digest_file.delete("alice", "htauth")
|
54
|
-
@digest_file.contents.
|
53
|
+
@digest_file.contents.must_equal IO.read(DIGEST_DELETE_TEST_FILE)
|
55
54
|
end
|
56
55
|
|
57
56
|
it "is usable in a ruby manner and yeilds itself when opened" do
|
@@ -60,7 +59,7 @@ describe HTAuth::DigestFile do
|
|
60
59
|
pf.delete('bob', 'htauth')
|
61
60
|
end
|
62
61
|
lines = IO.readlines(@tf.path)
|
63
|
-
lines.size.
|
64
|
-
lines.first.strip.
|
62
|
+
lines.size.must_equal 1
|
63
|
+
lines.first.strip.must_equal "alice:htauth:2f361db93147d84831eb34f19d05bfbb"
|
65
64
|
end
|
66
65
|
end
|
data/spec/digest_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'htauth/digest'
|
3
3
|
require 'tempfile'
|
4
4
|
|
@@ -41,8 +41,8 @@ describe HTAuth::Digest do
|
|
41
41
|
begin
|
42
42
|
@rdigest.run([ "-h" ])
|
43
43
|
rescue SystemExit => se
|
44
|
-
se.status.
|
45
|
-
@stdout.string.
|
44
|
+
se.status.must_equal 1
|
45
|
+
@stdout.string.must_match( /passwordfile realm username/m )
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -50,8 +50,8 @@ describe HTAuth::Digest do
|
|
50
50
|
begin
|
51
51
|
@rdigest.run([ "--version" ])
|
52
52
|
rescue SystemExit => se
|
53
|
-
se.status.
|
54
|
-
@stdout.string.
|
53
|
+
se.status.must_equal 1
|
54
|
+
@stdout.string.must_match( /version #{HTAuth::VERSION}/ )
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -62,8 +62,8 @@ describe HTAuth::Digest do
|
|
62
62
|
@stdin.rewind
|
63
63
|
@rdigest.run([ "-c", @new_file, "htauth", "bob" ])
|
64
64
|
rescue SystemExit => se
|
65
|
-
se.status.
|
66
|
-
IO.read(@new_file).
|
65
|
+
se.status.must_equal 0
|
66
|
+
IO.read(@new_file).must_equal IO.readlines(DIGEST_ORIGINAL_TEST_FILE).first
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -74,8 +74,8 @@ describe HTAuth::Digest do
|
|
74
74
|
@stdin.rewind
|
75
75
|
@rdigest.run([ "-c", @tf.path, "htauth", "bob"])
|
76
76
|
rescue SystemExit => se
|
77
|
-
se.status.
|
78
|
-
IO.read(@tf.path).
|
77
|
+
se.status.must_equal 0
|
78
|
+
IO.read(@tf.path).must_equal IO.read(DIGEST_DELETE_TEST_FILE)
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -86,8 +86,8 @@ describe HTAuth::Digest do
|
|
86
86
|
@stdin.rewind
|
87
87
|
@rdigest.run([ @tf.path, "htauth-new", "charlie" ])
|
88
88
|
rescue SystemExit => se
|
89
|
-
se.status.
|
90
|
-
IO.read(@tf.path).
|
89
|
+
se.status.must_equal 0
|
90
|
+
IO.read(@tf.path).must_equal IO.read(DIGEST_ADD_TEST_FILE)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -98,9 +98,9 @@ describe HTAuth::Digest do
|
|
98
98
|
@stdin.rewind
|
99
99
|
@rdigest.run([ @tf.path, "htauth", "alice" ])
|
100
100
|
rescue SystemExit => se
|
101
|
-
@stderr.string.
|
102
|
-
se.status.
|
103
|
-
IO.read(@tf.path).
|
101
|
+
@stderr.string.must_equal ""
|
102
|
+
se.status.must_equal 0
|
103
|
+
IO.read(@tf.path).must_equal IO.read(DIGEST_UPDATE_TEST_FILE)
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -108,9 +108,9 @@ describe HTAuth::Digest do
|
|
108
108
|
begin
|
109
109
|
@rdigest.run([ "-d", @tf.path, "htauth", "alice" ])
|
110
110
|
rescue SystemExit => se
|
111
|
-
@stderr.string.
|
112
|
-
se.status.
|
113
|
-
IO.read(@tf.path).
|
111
|
+
@stderr.string.must_equal ""
|
112
|
+
se.status.must_equal 0
|
113
|
+
IO.read(@tf.path).must_equal IO.read(DIGEST_DELETE_TEST_FILE)
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
@@ -121,8 +121,8 @@ describe HTAuth::Digest do
|
|
121
121
|
@stdin.rewind
|
122
122
|
@rdigest.run([ "-c", "/etc/you-cannot-create-me", "htauth", "alice"])
|
123
123
|
rescue SystemExit => se
|
124
|
-
@stderr.string.
|
125
|
-
se.status.
|
124
|
+
@stderr.string.must_match( %r{Could not open password file /etc/you-cannot-create-me}m )
|
125
|
+
se.status.must_equal 1
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
@@ -133,8 +133,8 @@ describe HTAuth::Digest do
|
|
133
133
|
@stdin.rewind
|
134
134
|
@rdigest.run([ @tf.path, "htauth", "alice"])
|
135
135
|
rescue SystemExit => se
|
136
|
-
@stderr.string.
|
137
|
-
se.status.
|
136
|
+
@stderr.string.must_match( /They don't match, sorry./m )
|
137
|
+
se.status.must_equal 1
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
@@ -142,8 +142,8 @@ describe HTAuth::Digest do
|
|
142
142
|
begin
|
143
143
|
@rdigest.run(["--blah"])
|
144
144
|
rescue SystemExit => se
|
145
|
-
@stderr.string.
|
146
|
-
se.status.
|
145
|
+
@stderr.string.must_match( /ERROR:/m )
|
146
|
+
se.status.must_equal 1
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
data/spec/md5_spec.rb
CHANGED
@@ -4,14 +4,14 @@ require 'htauth/md5'
|
|
4
4
|
|
5
5
|
describe HTAuth::Md5 do
|
6
6
|
it "has a prefix" do
|
7
|
-
HTAuth::Md5.new.prefix.
|
7
|
+
HTAuth::Md5.new.prefix.must_equal "$apr1$"
|
8
8
|
end
|
9
9
|
|
10
10
|
it "encrypts the same way that apache does" do
|
11
11
|
apache_salt = "L0LDd/.."
|
12
12
|
apache_result = "$apr1$L0LDd/..$yhUzDjpxam5F1kWdtwMco1"
|
13
13
|
md5 = HTAuth::Md5.new({ 'salt' => apache_salt })
|
14
|
-
md5.encode("a secret").
|
14
|
+
md5.encode("a secret").must_equal apache_result
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
data/spec/passwd_entry_spec.rb
CHANGED
@@ -1,139 +1,138 @@
|
|
1
|
-
|
2
|
-
require File.join(File.dirname(__FILE__),"spec_helper.rb")
|
3
|
-
|
1
|
+
require 'spec_helper'
|
4
2
|
require 'htauth/passwd_entry'
|
5
3
|
|
6
4
|
describe HTAuth::PasswdEntry do
|
7
5
|
before(:each) do
|
8
6
|
@alice = HTAuth::PasswdEntry.new("alice", "a secret", "crypt", { :salt => "mD" })
|
9
7
|
@bob = HTAuth::PasswdEntry.new("bob", "b secret", "crypt", { :salt => "b8"})
|
8
|
+
@salt = "lo1tk/.."
|
10
9
|
end
|
11
10
|
|
12
11
|
it "initializes with a user and realm" do
|
13
|
-
@alice.user.
|
12
|
+
@alice.user.must_equal "alice"
|
14
13
|
end
|
15
14
|
|
16
15
|
it "has the correct crypt password" do
|
17
16
|
@alice.password = "a secret"
|
18
|
-
@alice.digest.
|
17
|
+
@alice.digest.must_equal "mDwdZuXalQ5zk"
|
19
18
|
end
|
20
19
|
|
21
|
-
it "
|
22
|
-
bob = HTAuth::PasswdEntry.new("bob", "b secret", "md5", { :salt =>
|
23
|
-
bob.digest.
|
20
|
+
it "encrypts correctly for md5" do
|
21
|
+
bob = HTAuth::PasswdEntry.new("bob", "b secret", "md5", { :salt => @salt })
|
22
|
+
bob.digest.must_equal "$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1"
|
24
23
|
end
|
25
24
|
|
26
|
-
it "
|
25
|
+
it "encrypts correctly for sha1" do
|
27
26
|
bob = HTAuth::PasswdEntry.new("bob", "b secret", "sha1", { :salt => @salt })
|
28
|
-
bob.digest.
|
27
|
+
bob.digest.must_equal "{SHA}b/tjGXbX80MEKVnF200S43ca4hY="
|
29
28
|
end
|
30
29
|
|
31
|
-
it "
|
30
|
+
it "encrypts correctly for plaintext" do
|
32
31
|
bob = HTAuth::PasswdEntry.new("bob", "b secret", "plaintext", { :salt => @salt })
|
33
|
-
bob.digest.
|
32
|
+
bob.digest.must_equal "b secret"
|
34
33
|
end
|
35
34
|
|
36
35
|
it "encrypts with crypt as a default, when parsed from crypt()'d line" do
|
37
36
|
bob2 = HTAuth::PasswdEntry.from_line(@bob.to_s)
|
38
|
-
bob2.algorithm.
|
39
|
-
bob2.algorithm.
|
37
|
+
bob2.algorithm.must_be_instance_of( Array )
|
38
|
+
bob2.algorithm.size.must_equal 2
|
40
39
|
bob2.password = "another secret"
|
41
|
-
bob2.algorithm.
|
40
|
+
bob2.algorithm.must_be_instance_of(HTAuth::Crypt)
|
42
41
|
end
|
43
42
|
|
44
43
|
it "encrypts with crypt as a default, when parsed from plaintext line" do
|
45
44
|
p = HTAuth::PasswdEntry.new('paul', 'p secret', 'plaintext')
|
46
45
|
p2 = HTAuth::PasswdEntry.from_line(p.to_s)
|
47
|
-
p2.algorithm.
|
48
|
-
p2.algorithm.
|
46
|
+
p2.algorithm.must_be_instance_of(Array)
|
47
|
+
p2.algorithm.size.must_equal 2
|
49
48
|
p2.password = "another secret"
|
50
|
-
p2.algorithm.
|
49
|
+
p2.algorithm.must_be_instance_of(HTAuth::Crypt)
|
51
50
|
end
|
52
51
|
|
53
52
|
it "encrypts with md5 as default, when parsed from an md5 line" do
|
54
53
|
m = HTAuth::PasswdEntry.new("mary", "m secret", "md5")
|
55
54
|
m2 = HTAuth::PasswdEntry.from_line(m.to_s)
|
56
|
-
m2.algorithm.
|
55
|
+
m2.algorithm.must_be_instance_of(HTAuth::Md5)
|
57
56
|
end
|
58
57
|
|
59
58
|
it "encrypts with sha1 as default, when parsed from an sha1 line" do
|
60
59
|
s = HTAuth::PasswdEntry.new("steve", "s secret", "sha1")
|
61
60
|
s2 = HTAuth::PasswdEntry.from_line(s.to_s)
|
62
|
-
s2.algorithm.
|
61
|
+
s2.algorithm.must_be_instance_of(HTAuth::Sha1)
|
63
62
|
end
|
64
63
|
|
65
64
|
it "determins the algorithm to be crypt when checking a password" do
|
66
65
|
bob2 = HTAuth::PasswdEntry.from_line(@bob.to_s)
|
67
|
-
bob2.algorithm.
|
68
|
-
bob2.algorithm.
|
69
|
-
bob2.authenticated?("b secret").
|
70
|
-
bob2.algorithm.
|
66
|
+
bob2.algorithm.must_be_instance_of(Array)
|
67
|
+
bob2.algorithm.size.must_equal 2
|
68
|
+
bob2.authenticated?("b secret").must_equal true
|
69
|
+
bob2.algorithm.must_be_instance_of(HTAuth::Crypt)
|
71
70
|
end
|
72
71
|
|
73
72
|
it "determins the algorithm to be plain when checking a password" do
|
74
73
|
bob2 = HTAuth::PasswdEntry.from_line("bob:b secret")
|
75
|
-
bob2.algorithm.
|
76
|
-
bob2.algorithm.
|
77
|
-
bob2.authenticated?("b secret").
|
78
|
-
bob2.algorithm.
|
74
|
+
bob2.algorithm.must_be_instance_of(Array)
|
75
|
+
bob2.algorithm.size.must_equal 2
|
76
|
+
bob2.authenticated?("b secret").must_equal true
|
77
|
+
bob2.algorithm.must_be_instance_of(HTAuth::Plaintext)
|
79
78
|
end
|
80
79
|
|
81
80
|
it "authenticates correctly against md5" do
|
82
81
|
m = HTAuth::PasswdEntry.new("mary", "m secret", "md5")
|
83
82
|
m2 = HTAuth::PasswdEntry.from_line(m.to_s)
|
84
|
-
m2.authenticated?("m secret").
|
83
|
+
m2.authenticated?("m secret").must_equal true
|
85
84
|
end
|
86
85
|
|
87
86
|
it "authenticates correctly against sha1" do
|
88
87
|
s = HTAuth::PasswdEntry.new("steve", "s secret", "sha1")
|
89
88
|
s2 = HTAuth::PasswdEntry.from_line(s.to_s)
|
90
|
-
s2.authenticated?("s secret").
|
89
|
+
s2.authenticated?("s secret").must_equal true
|
91
90
|
end
|
92
91
|
|
93
92
|
|
94
93
|
|
95
94
|
|
96
95
|
it "returns username for a key" do
|
97
|
-
@alice.key.
|
96
|
+
@alice.key.must_equal "alice"
|
98
97
|
end
|
99
98
|
|
100
99
|
it "checks the password correctly" do
|
101
|
-
@bob.authenticated?("b secret").
|
100
|
+
@bob.authenticated?("b secret").must_equal true
|
102
101
|
end
|
103
102
|
|
104
103
|
it "formats correctly when put to a string" do
|
105
|
-
@bob.to_s.
|
104
|
+
@bob.to_s.must_equal "bob:b8Ml4Jp9I0N8E"
|
106
105
|
end
|
107
106
|
|
108
107
|
it "parses an input line" do
|
109
108
|
@bob_new = HTAuth::PasswdEntry.from_line("bob:b8Ml4Jp9I0N8E")
|
110
|
-
@bob.user.
|
111
|
-
@bob.digest.
|
109
|
+
@bob.user.must_equal @bob_new.user
|
110
|
+
@bob.digest.must_equal @bob_new.digest
|
112
111
|
end
|
113
112
|
|
114
113
|
it "knows if an input line is a possible entry and raises an exception" do
|
115
|
-
lambda { HTAuth::PasswdEntry.is_entry!("#stuff") }.
|
116
|
-
lambda { HTAuth::PasswdEntry.is_entry!("this:that:other:stuff") }.
|
117
|
-
lambda { HTAuth::PasswdEntry.is_entry!("this:that:other") }.
|
118
|
-
lambda { HTAuth::PasswdEntry.is_entry!("this:that:0a90549e8ffb2dd62f98252a95d88xyz") }.
|
114
|
+
lambda { HTAuth::PasswdEntry.is_entry!("#stuff") }.must_raise(HTAuth::InvalidPasswdEntry)
|
115
|
+
lambda { HTAuth::PasswdEntry.is_entry!("this:that:other:stuff") }.must_raise(HTAuth::InvalidPasswdEntry)
|
116
|
+
lambda { HTAuth::PasswdEntry.is_entry!("this:that:other") }.must_raise(HTAuth::InvalidPasswdEntry)
|
117
|
+
lambda { HTAuth::PasswdEntry.is_entry!("this:that:0a90549e8ffb2dd62f98252a95d88xyz") }.must_raise(HTAuth::InvalidPasswdEntry)
|
119
118
|
end
|
120
119
|
|
121
120
|
it "knows if an input line is a possible entry and returns false" do
|
122
|
-
HTAuth::PasswdEntry.is_entry?("#stuff").
|
123
|
-
HTAuth::PasswdEntry.is_entry?("this:that:other:stuff").
|
124
|
-
HTAuth::PasswdEntry.is_entry?("this:that:other").
|
125
|
-
HTAuth::PasswdEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz").
|
121
|
+
HTAuth::PasswdEntry.is_entry?("#stuff").must_equal false
|
122
|
+
HTAuth::PasswdEntry.is_entry?("this:that:other:stuff").must_equal false
|
123
|
+
HTAuth::PasswdEntry.is_entry?("this:that:other").must_equal false
|
124
|
+
HTAuth::PasswdEntry.is_entry?("this:that:0a90549e8ffb2dd62f98252a95d88xyz").must_equal false
|
126
125
|
end
|
127
126
|
|
128
127
|
it "knows if an input line is a possible entry and returns true" do
|
129
|
-
HTAuth::PasswdEntry.is_entry?("bob:irRm0g.SDfCyI").
|
130
|
-
HTAuth::PasswdEntry.is_entry?("bob:b secreat").
|
131
|
-
HTAuth::PasswdEntry.is_entry?("bob:{SHA}b/tjGXbX80MEKVnF200S43ca4hY=").
|
132
|
-
HTAuth::PasswdEntry.is_entry?("bob:$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1").
|
128
|
+
HTAuth::PasswdEntry.is_entry?("bob:irRm0g.SDfCyI").must_equal true
|
129
|
+
HTAuth::PasswdEntry.is_entry?("bob:b secreat").must_equal true
|
130
|
+
HTAuth::PasswdEntry.is_entry?("bob:{SHA}b/tjGXbX80MEKVnF200S43ca4hY=").must_equal true
|
131
|
+
HTAuth::PasswdEntry.is_entry?("bob:$apr1$lo1tk/..$CarApvZPee0F6Wj1U0GxZ1").must_equal true
|
133
132
|
|
134
133
|
end
|
135
134
|
|
136
135
|
it "duplicates itself" do
|
137
|
-
@alice.dup.to_s.
|
136
|
+
@alice.dup.to_s.must_equal @alice.to_s
|
138
137
|
end
|
139
138
|
end
|
data/spec/passwd_file_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'htauth/passwd_file'
|
4
3
|
require 'tempfile'
|
5
4
|
|
@@ -23,35 +22,35 @@ describe HTAuth::PasswdFile do
|
|
23
22
|
|
24
23
|
it "can add a new entry to an already existing passwd file" do
|
25
24
|
@passwd_file.add_or_update("charlie", "c secret", "sha1")
|
26
|
-
@passwd_file.contents.
|
25
|
+
@passwd_file.contents.must_equal IO.read(PASSWD_ADD_TEST_FILE)
|
27
26
|
end
|
28
27
|
|
29
28
|
it "can tell if an entry already exists in the passwd file" do
|
30
|
-
@passwd_file.has_entry?("alice").
|
31
|
-
@passwd_file.has_entry?("david").
|
29
|
+
@passwd_file.has_entry?("alice").must_equal true
|
30
|
+
@passwd_file.has_entry?("david").must_equal false
|
32
31
|
end
|
33
32
|
|
34
33
|
it "can update an entry in an already existing passwd file, algorithm can change" do
|
35
34
|
@passwd_file.add_or_update("alice", "a new secret", "sha1")
|
36
|
-
@passwd_file.contents.
|
35
|
+
@passwd_file.contents.must_equal IO.read(PASSWD_UPDATE_TEST_FILE)
|
37
36
|
end
|
38
37
|
|
39
38
|
it "fetches a copy of an entry" do
|
40
|
-
@passwd_file.fetch("alice").to_s.
|
39
|
+
@passwd_file.fetch("alice").to_s.must_equal "alice:$apr1$DghnA...$CsPcgerfsI/Ryy0AOAJtb0"
|
41
40
|
end
|
42
41
|
|
43
42
|
it "raises an error if an attempt is made to alter a non-existenet file" do
|
44
|
-
lambda { HTAuth::PasswdFile.new("some-file") }.
|
43
|
+
lambda { HTAuth::PasswdFile.new("some-file") }.must_raise(HTAuth::FileAccessError)
|
45
44
|
end
|
46
45
|
|
47
46
|
# this test will only work on systems that have /etc/ssh_host_rsa_key
|
48
47
|
it "raises an error if an attempt is made to open a file where no permissions are granted" do
|
49
|
-
lambda { HTAuth::PasswdFile.new("/etc/ssh_host_rsa_key") }.
|
48
|
+
lambda { HTAuth::PasswdFile.new("/etc/ssh_host_rsa_key") }.must_raise(HTAuth::FileAccessError)
|
50
49
|
end
|
51
50
|
|
52
51
|
it "deletes an entry" do
|
53
52
|
@passwd_file.delete("bob")
|
54
|
-
@passwd_file.contents.
|
53
|
+
@passwd_file.contents.must_equal IO.read(PASSWD_DELETE_TEST_FILE)
|
55
54
|
end
|
56
55
|
|
57
56
|
it "is usable in a ruby manner and yeilds itself when opened" do
|
@@ -60,8 +59,8 @@ describe HTAuth::PasswdFile do
|
|
60
59
|
pf.delete('bob')
|
61
60
|
end
|
62
61
|
lines = IO.readlines(@tf.path)
|
63
|
-
lines.size.
|
64
|
-
lines.first.split(':').first.
|
65
|
-
lines.first.split(':').last.
|
62
|
+
lines.size.must_equal 1
|
63
|
+
lines.first.split(':').first.must_equal "alice"
|
64
|
+
lines.first.split(':').last.must_match( /\$apr1\$/ )
|
66
65
|
end
|
67
66
|
end
|