Class Jabber::SASL::DigestMD5
In: lib/xmpp4r/sasl.rb
Parent: Base
XMLStanza Message Presence Iq REXML::Element X IqQuery Error StreamHost IqSiFileRange IqSiFile StreamHostUsed IqSi XRosterItem RosterItem IqFeature XMUCUserItem XMUCUserInvite Feature Identity Item XDataField XDataReported XDataTitle XDataInstructions IqVcard Singleton IdGenerator Connection Client Component Comparable JID RuntimeError ErrorException AuthenticationFailure SOCKS5Error Stream SOCKS5Bytestreams SOCKS5BytestreamsTarget SOCKS5BytestreamsInitiator SOCKS5BytestreamsServerStreamHost TCPSocket SOCKS5Socket IqQuery IqQueryBytestreams IqQueryVersion IqQueryRoster IqQueryDiscoItems IqQueryDiscoInfo IBB IBBTarget IBBInitiator Responder SimpleResponder X XRoster XMUCUser XMUC XDelay XData MUCClient SimpleMUCClient Base DigestMD5 Plain FileSource StreamParser SOCKS5BytestreamsPeer SOCKS5BytestreamsServer IBBQueueItem Helper MUCBrowser Helper Helper lib/xmpp4r/authenticationfailure.rb lib/xmpp4r/idgenerator.rb lib/xmpp4r/connection.rb lib/xmpp4r/iq.rb lib/xmpp4r/jid.rb lib/xmpp4r/xmlstanza.rb lib/xmpp4r/errorexception.rb lib/xmpp4r/stream.rb lib/xmpp4r/client.rb lib/xmpp4r/streamparser.rb lib/xmpp4r/x.rb lib/xmpp4r/error.rb lib/xmpp4r/component.rb lib/xmpp4r/query.rb lib/xmpp4r/message.rb lib/xmpp4r/presence.rb lib/xmpp4r/bytestreams/helper/ibb/initiator.rb lib/xmpp4r/bytestreams/iq/si.rb lib/xmpp4r/bytestreams/iq/bytestreams.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb lib/xmpp4r/bytestreams/helper/ibb/base.rb lib/xmpp4r/bytestreams/helper/ibb/target.rb Bytestreams lib/xmpp4r/version/iq/version.rb lib/xmpp4r/version/helper/responder.rb lib/xmpp4r/version/helper/simpleresponder.rb Version lib/xmpp4r/roster/helper/roster.rb lib/xmpp4r/roster/iq/roster.rb lib/xmpp4r/roster/x/roster.rb Roster lib/xmpp4r/feature_negotiation/iq/feature.rb FeatureNegotiation lib/xmpp4r/muc/x/muc.rb lib/xmpp4r/muc/helper/mucclient.rb lib/xmpp4r/muc/x/mucuseritem.rb lib/xmpp4r/muc/helper/mucbrowser.rb lib/xmpp4r/muc/x/mucuserinvite.rb lib/xmpp4r/muc/helper/simplemucclient.rb MUC lib/xmpp4r/sasl.rb SASL lib/xmpp4r/delay/x/delay.rb Delay lib/xmpp4r/bytestreams/helper/filetransfer.rb TransferSource FileTransfer lib/xmpp4r/discovery/iq/discoinfo.rb lib/xmpp4r/discovery/iq/discoitems.rb Discovery lib/xmpp4r/dataforms/x/data.rb Dataforms lib/xmpp4r/vcard/helper/vcard.rb lib/xmpp4r/vcard/iq/vcard.rb Vcard Jabber Module: Jabber

SASL DIGEST-MD5 authentication helper (RFC2831)

Methods

auth   h   hh   new   response_value  

Public Class methods

Sends the wished auth mechanism and wait for a challenge

(proceed with DigestMD5#auth)

[Source]

    # File lib/xmpp4r/sasl.rb, line 74
74:       def initialize(stream)
75:         super
76: 
77:         challenge = {}
78:         error = nil
79:         @stream.send(generate_auth('DIGEST-MD5')) { |reply|
80:           if reply.name == 'challenge' and reply.namespace == NS_SASL
81:             challenge_text = Base64::decode64(reply.text)
82:             challenge_text.split(/,/).each { |s|
83:               key, value = s.split(/=/, 2)
84:               value.sub!(/^"/, '')
85:               value.sub!(/"$/, '')
86:               challenge[key] = value
87:             }
88:           else
89:             error = reply.first_element(nil).name
90:           end
91:           true
92:         }
93:         raise error if error
94: 
95:         @nonce = challenge['nonce']
96:         @realm = challenge['realm']
97:       end

Public Instance methods

  • Send a response
  • Wait for the server’s challenge (which aren’t checked)
  • Send a blind response to the server’s challenge

[Source]

     # File lib/xmpp4r/sasl.rb, line 103
103:       def auth(password)
104:         response = {}
105:         response['nonce'] = @nonce
106:         response['charset'] = 'utf-8'
107:         response['username'] = @stream.jid.node
108:         response['realm'] = @realm || @stream.jid.domain
109:         response['cnonce'] = generate_nonce
110:         response['nc'] = '00000001'
111:         response['qop'] = 'auth'
112:         response['digest-uri'] = "xmpp/#{@stream.jid.domain}"
113:         response['response'] = response_value(@stream.jid.node, @stream.jid.domain, response['digest-uri'], password, @nonce, response['cnonce'], response['qop'])
114:         response.each { |key,value|
115:           unless %w(nc qop response charset).include? key
116:             response[key] = "\"#{value}\""
117:           end
118:         }
119: 
120:         r = REXML::Element.new('response')
121:         r.add_namespace NS_SASL
122:         r.text = Base64::encode64(response.collect { |k,v| "#{k}=#{v}" }.join(',')).gsub(/\s/, '')
123:         error = nil
124:         @stream.send(r) { |reply|
125:           if reply.name != 'challenge'
126:             error = reply.first_element(nil).name
127:           end
128:           true
129:         }
130:         
131:         raise error if error
132: 
133:         # TODO: check the challenge from the server
134: 
135:         r.text = nil
136:         @stream.send(r) { |reply|
137:           if reply.name != 'success'
138:             error = reply.first_element(nil).name
139:           end
140:           true
141:         }
142:         
143:         raise error if error
144:       end

Private Instance methods

Function from RFC2831

[Source]

     # File lib/xmpp4r/sasl.rb, line 150
150:       def h(s); Digest::MD5.digest(s); end

Function from RFC2831

[Source]

     # File lib/xmpp4r/sasl.rb, line 153
153:       def hh(s); Digest::MD5.hexdigest(s); end

Calculate the value for the response field

[Source]

     # File lib/xmpp4r/sasl.rb, line 157
157:       def response_value(username, realm, digest_uri, passwd, nonce, cnonce, qop)
158:         a1_h = h("#{username}:#{realm}:#{passwd}")
159:         a1 = "#{a1_h}:#{nonce}:#{cnonce}"
160:         #a2 = "AUTHENTICATE:#{digest_uri}#{(qop == 'auth') ? '' : ':00000000000000000000000000000000'}"
161:         a2 = "AUTHENTICATE:#{digest_uri}"
162: 
163:         hh("#{hh(a1)}:#{nonce}:00000001:#{cnonce}:#{qop}:#{hh(a2)}")
164:       end

[Validate]