htauth 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|