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 170 170: def auth(password) 171: response = {} 172: response['nonce'] = @nonce 173: response['charset'] = 'utf-8' 174: response['username'] = @stream.jid.node 175: response['realm'] = @realm || @stream.jid.domain 176: response['cnonce'] = generate_nonce 177: response['nc'] = '00000001' 178: response['qop'] = 'auth' 179: response['digest-uri'] = "xmpp/#{@stream.jid.domain}" 180: response['response'] = response_value(@stream.jid.node, @stream.jid.domain, response['digest-uri'], password, @nonce, response['cnonce'], response['qop'], response['authzid']) 181: response.each { |key,value| 182: unless %w(nc qop response charset).include? key 183: response[key] = "\"#{value}\"" 184: end 185: } 186: 187: response_text = response.collect { |k,v| "#{k}=#{v}" }.join(',') 188: Jabber::debuglog("SASL DIGEST-MD5 response:\n#{response_text}\n#{response.inspect}") 189: 190: r = REXML::Element.new('response') 191: r.add_namespace NS_SASL 192: r.text = Base64::encode64(response_text).gsub(/\s/, '') 193: 194: success_already = false 195: error = nil 196: @stream.send(r) { |reply| 197: if reply.name == 'success' 198: success_already = true 199: elsif reply.name != 'challenge' 200: error = reply.first_element(nil).name 201: end 202: true 203: } 204: 205: return if success_already 206: raise error if error 207: 208: # TODO: check the challenge from the server 209: 210: r.text = nil 211: @stream.send(r) { |reply| 212: if reply.name != 'success' 213: error = reply.first_element(nil).name 214: end 215: true 216: } 217: 218: raise error if error 219: 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: text.scan(/./) do |ch| 126: if state == :key 127: if ch == '=' 128: state = :value 129: else 130: key += ch 131: end 132: 133: elsif state == :value 134: if ch == ',' 135: # due to our home-made parsing of the challenge, the key could have 136: # leading whitespace. strip it, or that would break jabberd2 support. 137: key = key.strip 138: res[key] = value 139: key = '' 140: value = '' 141: state = :key 142: elsif ch == '"' and value == '' 143: state = :quote 144: else 145: value += ch 146: end 147: 148: elsif state == :quote 149: if ch == '"' 150: state = :value 151: else 152: value += ch 153: end 154: end 155: end 156: # due to our home-made parsing of the challenge, the key could have 157: # leading whitespace. strip it, or that would break jabberd2 support. 158: key = key.strip 159: res[key] = value unless key == '' 160: 161: Jabber::debuglog("SASL DIGEST-MD5 challenge:\n#{text}\n#{res.inspect}") 162: 163: res 164: end