|
16 | 16 |
|
17 | 17 | require "socket" |
18 | 18 | require "monitor" |
19 | | -require "digest/md5" |
20 | | -require "strscan" |
21 | 19 | require 'net/protocol' |
22 | 20 | begin |
23 | 21 | require "openssl" |
@@ -292,31 +290,6 @@ def self.max_flag_count=(count) |
292 | 290 | @@max_flag_count = count |
293 | 291 | end |
294 | 292 |
|
295 | | - # Adds an authenticator for Net::IMAP#authenticate. +auth_type+ |
296 | | - # is the type of authentication this authenticator supports |
297 | | - # (for instance, "LOGIN"). The +authenticator+ is an object |
298 | | - # which defines a process() method to handle authentication with |
299 | | - # the server. See Net::IMAP::LoginAuthenticator, |
300 | | - # Net::IMAP::CramMD5Authenticator, and Net::IMAP::DigestMD5Authenticator |
301 | | - # for examples. |
302 | | - # |
303 | | - # |
304 | | - # If +auth_type+ refers to an existing authenticator, it will be |
305 | | - # replaced by the new one. |
306 | | - def self.add_authenticator(auth_type, authenticator) |
307 | | - @@authenticators[auth_type] = authenticator |
308 | | - end |
309 | | - |
310 | | - # Builds an authenticator for Net::IMAP#authenticate. |
311 | | - def self.authenticator(auth_type, *args) |
312 | | - auth_type = auth_type.upcase |
313 | | - unless @@authenticators.has_key?(auth_type) |
314 | | - raise ArgumentError, |
315 | | - format('unknown auth type - "%s"', auth_type) |
316 | | - end |
317 | | - @@authenticators[auth_type].new(*args) |
318 | | - end |
319 | | - |
320 | 293 | # The default port for IMAP connections, port 143 |
321 | 294 | def self.default_port |
322 | 295 | return PORT |
@@ -1124,7 +1097,6 @@ def self.format_datetime(time) |
1124 | 1097 | SSL_PORT = 993 # :nodoc: |
1125 | 1098 |
|
1126 | 1099 | @@debug = false |
1127 | | - @@authenticators = {} |
1128 | 1100 | @@max_flag_count = 10000 |
1129 | 1101 |
|
1130 | 1102 | # :call-seq: |
@@ -3901,182 +3873,6 @@ def parse_error(fmt, *args) |
3901 | 3873 | end |
3902 | 3874 | end |
3903 | 3875 |
|
3904 | | - # Authenticator for the "LOGIN" authentication type. See |
3905 | | - # #authenticate(). |
3906 | | - class LoginAuthenticator |
3907 | | - def process(data) |
3908 | | - case @state |
3909 | | - when STATE_USER |
3910 | | - @state = STATE_PASSWORD |
3911 | | - return @user |
3912 | | - when STATE_PASSWORD |
3913 | | - return @password |
3914 | | - end |
3915 | | - end |
3916 | | - |
3917 | | - private |
3918 | | - |
3919 | | - STATE_USER = :USER |
3920 | | - STATE_PASSWORD = :PASSWORD |
3921 | | - |
3922 | | - def initialize(user, password) |
3923 | | - @user = user |
3924 | | - @password = password |
3925 | | - @state = STATE_USER |
3926 | | - end |
3927 | | - end |
3928 | | - add_authenticator "LOGIN", LoginAuthenticator |
3929 | | - |
3930 | | - # Authenticator for the "PLAIN" authentication type. See |
3931 | | - # #authenticate(). |
3932 | | - class PlainAuthenticator |
3933 | | - def process(data) |
3934 | | - return "\0#{@user}\0#{@password}" |
3935 | | - end |
3936 | | - |
3937 | | - private |
3938 | | - |
3939 | | - def initialize(user, password) |
3940 | | - @user = user |
3941 | | - @password = password |
3942 | | - end |
3943 | | - end |
3944 | | - add_authenticator "PLAIN", PlainAuthenticator |
3945 | | - |
3946 | | - # Authenticator for the "CRAM-MD5" authentication type. See |
3947 | | - # #authenticate(). |
3948 | | - class CramMD5Authenticator |
3949 | | - def process(challenge) |
3950 | | - digest = hmac_md5(challenge, @password) |
3951 | | - return @user + " " + digest |
3952 | | - end |
3953 | | - |
3954 | | - private |
3955 | | - |
3956 | | - def initialize(user, password) |
3957 | | - @user = user |
3958 | | - @password = password |
3959 | | - end |
3960 | | - |
3961 | | - def hmac_md5(text, key) |
3962 | | - if key.length > 64 |
3963 | | - key = Digest::MD5.digest(key) |
3964 | | - end |
3965 | | - |
3966 | | - k_ipad = key + "\0" * (64 - key.length) |
3967 | | - k_opad = key + "\0" * (64 - key.length) |
3968 | | - for i in 0..63 |
3969 | | - k_ipad[i] = (k_ipad[i].ord ^ 0x36).chr |
3970 | | - k_opad[i] = (k_opad[i].ord ^ 0x5c).chr |
3971 | | - end |
3972 | | - |
3973 | | - digest = Digest::MD5.digest(k_ipad + text) |
3974 | | - |
3975 | | - return Digest::MD5.hexdigest(k_opad + digest) |
3976 | | - end |
3977 | | - end |
3978 | | - add_authenticator "CRAM-MD5", CramMD5Authenticator |
3979 | | - |
3980 | | - # Authenticator for the "DIGEST-MD5" authentication type. See |
3981 | | - # #authenticate(). |
3982 | | - class DigestMD5Authenticator |
3983 | | - def process(challenge) |
3984 | | - case @stage |
3985 | | - when STAGE_ONE |
3986 | | - @stage = STAGE_TWO |
3987 | | - sparams = {} |
3988 | | - c = StringScanner.new(challenge) |
3989 | | - while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/) |
3990 | | - k, v = c[1], c[2] |
3991 | | - if v =~ /^"(.*)"$/ |
3992 | | - v = $1 |
3993 | | - if v =~ /,/ |
3994 | | - v = v.split(',') |
3995 | | - end |
3996 | | - end |
3997 | | - sparams[k] = v |
3998 | | - end |
3999 | | - |
4000 | | - raise DataFormatError, "Bad Challenge: '#{challenge}'" unless c.rest.size == 0 |
4001 | | - raise Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth") |
4002 | | - |
4003 | | - response = { |
4004 | | - :nonce => sparams['nonce'], |
4005 | | - :username => @user, |
4006 | | - :realm => sparams['realm'], |
4007 | | - :cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]), |
4008 | | - :'digest-uri' => 'imap/' + sparams['realm'], |
4009 | | - :qop => 'auth', |
4010 | | - :maxbuf => 65535, |
4011 | | - :nc => "%08d" % nc(sparams['nonce']), |
4012 | | - :charset => sparams['charset'], |
4013 | | - } |
4014 | | - |
4015 | | - response[:authzid] = @authname unless @authname.nil? |
4016 | | - |
4017 | | - # now, the real thing |
4018 | | - a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') ) |
4019 | | - |
4020 | | - a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':') |
4021 | | - a1 << ':' + response[:authzid] unless response[:authzid].nil? |
4022 | | - |
4023 | | - a2 = "AUTHENTICATE:" + response[:'digest-uri'] |
4024 | | - a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/ |
4025 | | - |
4026 | | - response[:response] = Digest::MD5.hexdigest( |
4027 | | - [ |
4028 | | - Digest::MD5.hexdigest(a1), |
4029 | | - response.values_at(:nonce, :nc, :cnonce, :qop), |
4030 | | - Digest::MD5.hexdigest(a2) |
4031 | | - ].join(':') |
4032 | | - ) |
4033 | | - |
4034 | | - return response.keys.map {|key| qdval(key.to_s, response[key]) }.join(',') |
4035 | | - when STAGE_TWO |
4036 | | - @stage = nil |
4037 | | - # if at the second stage, return an empty string |
4038 | | - if challenge =~ /rspauth=/ |
4039 | | - return '' |
4040 | | - else |
4041 | | - raise ResponseParseError, challenge |
4042 | | - end |
4043 | | - else |
4044 | | - raise ResponseParseError, challenge |
4045 | | - end |
4046 | | - end |
4047 | | - |
4048 | | - def initialize(user, password, authname = nil) |
4049 | | - @user, @password, @authname = user, password, authname |
4050 | | - @nc, @stage = {}, STAGE_ONE |
4051 | | - end |
4052 | | - |
4053 | | - private |
4054 | | - |
4055 | | - STAGE_ONE = :stage_one |
4056 | | - STAGE_TWO = :stage_two |
4057 | | - |
4058 | | - def nc(nonce) |
4059 | | - if @nc.has_key? nonce |
4060 | | - @nc[nonce] = @nc[nonce] + 1 |
4061 | | - else |
4062 | | - @nc[nonce] = 1 |
4063 | | - end |
4064 | | - return @nc[nonce] |
4065 | | - end |
4066 | | - |
4067 | | - # some responses need quoting |
4068 | | - def qdval(k, v) |
4069 | | - return if k.nil? or v.nil? |
4070 | | - if %w"username authzid realm nonce cnonce digest-uri qop".include? k |
4071 | | - v.gsub!(/([\\"])/, "\\\1") |
4072 | | - return '%s="%s"' % [k, v] |
4073 | | - else |
4074 | | - return '%s=%s' % [k, v] |
4075 | | - end |
4076 | | - end |
4077 | | - end |
4078 | | - add_authenticator "DIGEST-MD5", DigestMD5Authenticator |
4079 | | - |
4080 | 3876 | # Superclass of IMAP errors. |
4081 | 3877 | class Error < StandardError |
4082 | 3878 | end |
@@ -4130,3 +3926,5 @@ class FlagCountError < Error |
4130 | 3926 | end |
4131 | 3927 | end |
4132 | 3928 | end |
| 3929 | + |
| 3930 | +require_relative "imap/authenticators" |
0 commit comments