Class Jabber::SASL::DigestMD5
In: lib/xmpp4r/sasl.rb
Parent: Base
XMPPElement ErrorResponse XMPPStanza X IqQuery Message Presence Iq JabberError ComponentAuthenticationFailure ArgumentError SOCKS5Error ServerError NoNameXmlnsRegistered ClientAuthenticationFailure Connection Client Component Client Singleton IdGenerator Comparable JID StandardError REXML::Element Stream IqQuery IqQueryRoster IqQueryBytestreams IqQueryVersion IqQueryRPC IqQueryMUCOwner IqQueryMUCAdmin IqQueryDiscoItems IqQueryDiscoInfo XRosterItem RosterXItem XMPPElement RosterItem StreamHost IqSiFile IqSiFileRange IqSi StreamHostUsed IqFeature C Body HTML UserItem XMUCUserInvite Configuration Items Item IqPubSub Publish Event IqPubSubOwner Subscription Unsubscribe Tune XDataField XDataReported XDataTitle XDataInstructions Feature Item Identity IqVcard XRoster RosterX X XMUC XMUCUser XDelay XData Iq IqCommand SOCKS5Bytestreams SOCKS5BytestreamsTarget SOCKS5BytestreamsInitiator SOCKS5BytestreamsServerStreamHost TCPSocket SOCKS5Socket IBB IBBTarget IBBInitiator Responder SimpleResponder XMLRPC::ParserWriterChooseMixin Client Server XMLRPC::ParseContentType XMLRPC::BasicServer MUCClient SimpleMUCClient MUC::UserItem XMUCUserItem IqQueryMUCAdminItem XParent SubscriptionConfig NodeConfig OwnerNodeConfig EventItems EventItem ServiceHelper NodeHelper Base Anonymous DigestMD5 Plain PubSub::ServiceHelper Helper FileSource Base Bot CallbackList Callback StreamParser Semaphore Helper Responder SOCKS5BytestreamsPeer SOCKS5BytestreamsServer IBBQueueItem Helper MUCBrowser NodeBrowser Helper Responder Helper lib/xmpp4r/message.rb lib/xmpp4r/connection.rb lib/xmpp4r/xmppstanza.rb lib/xmpp4r/iq.rb lib/xmpp4r/callbacks.rb lib/xmpp4r/idgenerator.rb lib/xmpp4r/stream.rb lib/xmpp4r/client.rb lib/xmpp4r/jid.rb lib/xmpp4r/x.rb lib/xmpp4r/streamparser.rb lib/xmpp4r/semaphore.rb lib/xmpp4r/errors.rb lib/xmpp4r/component.rb lib/xmpp4r/presence.rb lib/xmpp4r/xmppelement.rb lib/xmpp4r/query.rb lib/xmpp4r/roster/x/roster.rb lib/xmpp4r/roster/helper/roster.rb lib/xmpp4r/roster/iq/roster.rb Roster lib/xmpp4r/command/iq/command.rb lib/xmpp4r/command/helper/responder.rb Command XParent lib/xmpp4r/bytestreams/iq/si.rb lib/xmpp4r/bytestreams/helper/ibb/initiator.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/base.rb lib/xmpp4r/bytestreams/iq/bytestreams.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/initiator.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/socks5.rb lib/xmpp4r/bytestreams/helper/ibb/target.rb lib/xmpp4r/bytestreams/helper/socks5bytestreams/server.rb lib/xmpp4r/bytestreams/helper/ibb/base.rb Bytestreams lib/xmpp4r/version/helper/responder.rb lib/xmpp4r/version/helper/simpleresponder.rb lib/xmpp4r/version/iq/version.rb Version lib/xmpp4r/feature_negotiation/iq/feature.rb FeatureNegotiation lib/xmpp4r/caps/helper/helper.rb lib/xmpp4r/caps/c.rb Caps lib/xmpp4r/rpc/helper/server.rb lib/xmpp4r/rpc/helper/client.rb lib/xmpp4r/rpc/iq/rpc.rb RPC lib/xmpp4r/xhtml/html.rb XHTML lib/xmpp4r/muc/iq/mucadminitem.rb lib/xmpp4r/muc/x/muc.rb lib/xmpp4r/muc/item.rb lib/xmpp4r/muc/helper/simplemucclient.rb lib/xmpp4r/muc/iq/mucadmin.rb lib/xmpp4r/muc/helper/mucbrowser.rb lib/xmpp4r/muc/x/mucuseritem.rb lib/xmpp4r/muc/x/mucuserinvite.rb lib/xmpp4r/muc/iq/mucowner.rb lib/xmpp4r/muc/helper/mucclient.rb MUC lib/xmpp4r/delay/x/delay.rb Delay lib/xmpp4r/pubsub/children/item.rb lib/xmpp4r/pubsub/children/configuration.rb lib/xmpp4r/pubsub/children/subscription.rb lib/xmpp4r/pubsub/helper/servicehelper.rb lib/xmpp4r/pubsub/children/unsubscribe.rb lib/xmpp4r/pubsub/children/publish.rb lib/xmpp4r/pubsub/children/event.rb lib/xmpp4r/pubsub/iq/pubsub.rb lib/xmpp4r/pubsub/helper/nodebrowser.rb lib/xmpp4r/pubsub/helper/nodehelper.rb lib/xmpp4r/pubsub/children/items.rb lib/xmpp4r/pubsub/children/subscription_config.rb lib/xmpp4r/pubsub/children/node_config.rb PubSub lib/xmpp4r/sasl.rb SASL lib/xmpp4r/httpbinding/client.rb HTTPBinding lib/xmpp4r/tune/helper/helper.rb lib/xmpp4r/tune/tune.rb UserTune lib/xmpp4r/dataforms/x/data.rb Dataforms lib/xmpp4r/bytestreams/helper/filetransfer.rb TransferSource FileTransfer lib/xmpp4r/discovery/iq/discoinfo.rb lib/xmpp4r/discovery/helper/responder.rb lib/xmpp4r/discovery/iq/discoitems.rb Discovery lib/xmpp4r/framework/base.rb lib/xmpp4r/framework/bot.rb Framework lib/xmpp4r/vcard/helper/vcard.rb lib/xmpp4r/vcard/iq/vcard.rb Vcard Jabber dot/m_99_0.png

SASL DIGEST-MD5 authentication helper (RFC2831)

Methods

auth   decode_challenge   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 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

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 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

[Source]

     # 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

Private Instance methods

Function from RFC2831

[Source]

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

Function from RFC2831

[Source]

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

Calculate the value for the response field

[Source]

     # File lib/xmpp4r/sasl.rb, line 227
227:       def response_value(username, realm, digest_uri, passwd, nonce, cnonce, qop)
228:         a1_h = h("#{username}:#{realm}:#{passwd}")
229:         a1 = "#{a1_h}:#{nonce}:#{cnonce}"
230:         #a2 = "AUTHENTICATE:#{digest_uri}#{(qop == 'auth') ? '' : ':00000000000000000000000000000000'}"
231:         a2 = "AUTHENTICATE:#{digest_uri}"
232: 
233:         hh("#{hh(a1)}:#{nonce}:00000001:#{cnonce}:#{qop}:#{hh(a2)}")
234:       end

[Validate]