1
1
# frozen_string_literal: true
2
2
3
3
# Net::IMAP authenticator for the "`DIGEST-MD5`" SASL mechanism type, specified
4
- # in RFC2831( https://tools.ietf.org/html/rfc2831) . See Net::IMAP#authenticate.
4
+ # in RFC-2831[ https://tools.ietf.org/html/rfc2831] . See Net::IMAP#authenticate.
5
5
#
6
6
# == Deprecated
7
7
#
8
8
# "+DIGEST-MD5+" has been deprecated by
9
- # {RFC6331} [https://tools.ietf.org/html/rfc6331] and should not be relied on for
9
+ # RFC-6331 [https://tools.ietf.org/html/rfc6331] and should not be relied on for
10
10
# security. It is included for compatibility with existing servers.
11
11
class Net ::IMAP ::SASL ::DigestMD5Authenticator
12
12
STAGE_ONE = :stage_one
13
13
STAGE_TWO = :stage_two
14
14
private_constant :STAGE_ONE , :STAGE_TWO
15
15
16
- def initialize ( user , password , authname = nil , warn_deprecation : true )
16
+ # Authentication identity: the identity that matches the #password.
17
+ #
18
+ # RFC-2831[https://tools.ietf.org/html/rfc2831] uses the term +username+.
19
+ # "Authentication identity" is the generic term used by
20
+ # RFC-4422[https://tools.ietf.org/html/rfc4422].
21
+ # RFC-4616[https://tools.ietf.org/html/rfc4616] and many later RFCs abbreviate
22
+ # that to +authcid+. So +authcid+ is available as an alias for #username.
23
+ attr_reader :username
24
+
25
+ # A password or passphrase that matches the #username.
26
+ #
27
+ # The +password+ will be used to create the response digest.
28
+ attr_reader :password
29
+
30
+ # Authorization identity: an identity to act as or on behalf of. The identity
31
+ # form is application protocol specific. If not provided or left blank, the
32
+ # server derives an authorization identity from the authentication identity.
33
+ # The server is responsible for verifying the client's credentials and
34
+ # verifying that the identity it associates with the client's authentication
35
+ # identity is allowed to act as (or on behalf of) the authorization identity.
36
+ #
37
+ # For example, an administrator or superuser might take on another role:
38
+ #
39
+ # imap.authenticate "DIGEST-MD5", "root", ->{passwd}, authzid: "user"
40
+ #
41
+ attr_reader :authzid
42
+
43
+ # :call-seq:
44
+ # new(username, password, authzid = nil) -> authenticator
45
+ #
46
+ # Creates an Authenticator for the "+DIGEST-MD5+" SASL mechanism.
47
+ #
48
+ # Called by Net::IMAP#authenticate and similar methods on other clients.
49
+ #
50
+ # ==== Parameters
51
+ #
52
+ # * #username — Identity whose #password is used.
53
+ # * #password — A password or passphrase associated with this #username.
54
+ # * #authzid ― Alternate identity to act as or on behalf of. Optional.
55
+ # * +warn_deprecation+ — Set to +false+ to silence the warning.
56
+ #
57
+ # See the documentation for each attribute for more details.
58
+ def initialize ( username , password , authzid = nil , warn_deprecation : true )
17
59
if warn_deprecation
18
60
warn "WARNING: DIGEST-MD5 SASL mechanism was deprecated by RFC6331."
19
61
# TODO: recommend SCRAM instead.
20
62
end
21
63
require "digest/md5"
22
64
require "strscan"
23
- @user , @password , @authname = user , password , authname
65
+ @username , @password , @authzid = username , password , authzid
24
66
@nc , @stage = { } , STAGE_ONE
25
67
end
26
68
69
+ # Responds to server challenge in two stages.
27
70
def process ( challenge )
28
71
case @stage
29
72
when STAGE_ONE
@@ -46,7 +89,7 @@ def process(challenge)
46
89
47
90
response = {
48
91
:nonce => sparams [ 'nonce' ] ,
49
- :username => @user ,
92
+ :username => @username ,
50
93
:realm => sparams [ 'realm' ] ,
51
94
:cnonce => Digest ::MD5 . hexdigest ( "%.15f:%.15f:%d" % [ Time . now . to_f , rand , Process . pid . to_s ] ) ,
52
95
:'digest-uri' => 'imap/' + sparams [ 'realm' ] ,
@@ -56,7 +99,7 @@ def process(challenge)
56
99
:charset => sparams [ 'charset' ] ,
57
100
}
58
101
59
- response [ :authzid ] = @authname unless @authname . nil?
102
+ response [ :authzid ] = @authzid unless @authzid . nil?
60
103
61
104
# now, the real thing
62
105
a0 = Digest ::MD5 . digest ( [ response . values_at ( :username , :realm ) , @password ] . join ( ':' ) )
0 commit comments