| Class | Jabber::SASL::DigestMD5 |
| In: |
lib/xmpp4r/sasl.rb
|
| Parent: | Base |
SASL DIGEST-MD5 authentication helper (RFC2831)
Sends the wished auth mechanism and wait for a challenge
(proceed with DigestMD5#auth)
# File lib/xmpp4r/sasl.rb, line 99
99: def initialize(stream)
100: super
101:
102: challenge = {}
103: error = nil
104: @stream.send(generate_auth('DIGEST-MD5')) { |reply|
105: if reply.name == 'challenge' and reply.namespace == NS_SASL
106: challenge = decode_challenge(reply.text)
107: else
108: error = reply.first_element(nil).name
109: end
110: true
111: }
112: raise error if error
113:
114: @nonce = challenge['nonce']
115: @realm = challenge['realm']
116: end
# File lib/xmpp4r/sasl.rb, line 165
165: def auth(password)
166: response = {}
167: response['nonce'] = @nonce
168: response['charset'] = 'utf-8'
169: response['username'] = @stream.jid.node
170: response['realm'] = @realm || @stream.jid.domain
171: response['cnonce'] = generate_nonce
172: response['nc'] = '00000001'
173: response['qop'] = 'auth'
174: response['digest-uri'] = "xmpp/#{@stream.jid.domain}"
175: response['response'] = response_value(@stream.jid.node, @stream.jid.domain, response['digest-uri'], password, @nonce, response['cnonce'], response['qop'])
176: response.each { |key,value|
177: unless %w(nc qop response charset).include? key
178: response[key] = "\"#{value}\""
179: end
180: }
181:
182: response_text = response.collect { |k,v| "#{k}=#{v}" }.join(',')
183: Jabber::debuglog("SASL DIGEST-MD5 response:\n#{response_text}")
184:
185: r = REXML::Element.new('response')
186: r.add_namespace NS_SASL
187: r.text = Base64::encode64(response_text).gsub(/\s/, '')
188:
189: success_already = false
190: error = nil
191: @stream.send(r) { |reply|
192: if reply.name == 'success'
193: success_already = true
194: elsif reply.name != 'challenge'
195: error = reply.first_element(nil).name
196: end
197: true
198: }
199:
200: return if success_already
201: raise error if error
202:
203: # TODO: check the challenge from the server
204:
205: r.text = nil
206: @stream.send(r) { |reply|
207: if reply.name != 'success'
208: error = reply.first_element(nil).name
209: end
210: true
211: }
212:
213: raise error if error
214: end
# File lib/xmpp4r/sasl.rb, line 118
118: def decode_challenge(challenge)
119: text = Base64::decode64(challenge)
120: res = {}
121:
122: state = :key
123: key = ''
124: value = ''
125:
126: text.scan(/./) do |ch|
127: if state == :key
128: if ch == '='
129: state = :value
130: else
131: key += ch
132: end
133:
134: elsif state == :value
135: if ch == ','
136: res[key] = value
137: key = ''
138: value = ''
139: state = :key
140: elsif ch == '"' and value == ''
141: state = :quote
142: else
143: value += ch
144: end
145:
146: elsif state == :quote
147: if ch == '"'
148: state = :value
149: else
150: value += ch
151: end
152: end
153: end
154: res[key] = value unless key == ''
155:
156: Jabber::debuglog("SASL DIGEST-MD5 challenge:\n#{text.inspect}\n#{res.inspect}")
157:
158: res
159: end