net-http-digest_auth-1.4/0000755000004100000410000000000012222370721015445 5ustar www-datawww-datanet-http-digest_auth-1.4/checksums.yaml.gz.sig0000444000004100000410000000040012222370721021506 0ustar www-datawww-dataBn崫Ӛ1V1l)7[;zJIbR:$lc3bZ_$XȔ4]ܭrI8]3@4a?]LL4N}L/ǿQϳ[4;}^iT.CF?p: $U !UH lWjPFYu!VjifpsL#t>  (ݡni]B/{ 5O]x=Þ_|`1Ǟdv1net-http-digest_auth-1.4/sample/0000755000004100000410000000000012222370721016726 5ustar www-datawww-datanet-http-digest_auth-1.4/sample/auth_server.rb0000644000004100000410000000170012222370721021600 0ustar www-datawww-datarequire 'webrick' require 'tempfile' class AuthServlet < WEBrick::HTTPServlet::AbstractServlet @instance = nil def self.get_instance server, *options @instance ||= new(server, *options) end def initialize server super server config = {} config[:Realm] = 'net-http-digest_auth' config[:UseOpaque] = false config[:AutoReloadUserDB] = false passwd_file = Tempfile.new 'net-http-digest_auth' passwd_file.close htpasswd = WEBrick::HTTPAuth::Htpasswd.new passwd_file.path htpasswd.auth_type = WEBrick::HTTPAuth::DigestAuth htpasswd.set_passwd config[:Realm], 'username', 'password' htpasswd.flush config[:UserDB] = htpasswd @digest_auth = WEBrick::HTTPAuth::DigestAuth.new config end def do_GET req, res @digest_auth.authenticate req, res res.body = 'worked!' end end s = WEBrick::HTTPServer.new :Port => 8000 s.mount '/', AuthServlet trap 'INT' do s.shutdown end s.start net-http-digest_auth-1.4/sample/net_http_example.rb0000644000004100000410000000106612222370721022616 0ustar www-datawww-datarequire 'uri' require 'net/http' require 'net/http/digest_auth' uri = URI.parse 'http://localhost:8000/' uri.user = 'username' uri.password = 'password' h = Net::HTTP.new uri.host, uri.port h.set_debug_output $stderr req = Net::HTTP::Get.new uri.request_uri res = h.request req digest_auth = Net::HTTP::DigestAuth.new auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET' req = Net::HTTP::Get.new uri.request_uri req.add_field 'Authorization', auth res = h.request req puts puts "passed" if res.code == '200' puts "failed" if res.code != '200' net-http-digest_auth-1.4/test/0000755000004100000410000000000012222370721016424 5ustar www-datawww-datanet-http-digest_auth-1.4/test/test_net_http_digest_auth.rb0000644000004100000410000000624512222370721024224 0ustar www-datawww-datarequire 'minitest/autorun' require 'net/http/digest_auth' class TestNetHttpDigestAuth < MiniTest::Test def setup @uri = URI.parse "http://www.example.com/" @uri.user = 'user' @uri.password = 'password' @cnonce = '9ea5ff3bd34554a4165bbdc1df91dcff' @header = [ 'Digest qop="auth"', 'realm="www.example.com"', 'nonce="4107baa081a592a6021660200000cd6c5686ff5f579324402b374d83e2c9"' ].join ', ' @expected = [ 'Digest username="user"', 'realm="www.example.com"', 'algorithm=MD5', 'qop=auth', 'uri="/"', 'nonce="4107baa081a592a6021660200000cd6c5686ff5f579324402b374d83e2c9"', 'nc=00000000', 'cnonce="9ea5ff3bd34554a4165bbdc1df91dcff"', 'response="67be92a5e7b38d08679957db04f5da04"' ] @da = Net::HTTP::DigestAuth.new def @da.make_cnonce '9ea5ff3bd34554a4165bbdc1df91dcff' end end def expected @expected.join ', ' end def test_auth_header assert_equal expected, @da.auth_header(@uri, @header, 'GET') @expected[6] = 'nc=00000001' @expected[8] = 'response="1f5f0cd1588690c1303737f081c0b9bb"' assert_equal expected, @da.auth_header(@uri, @header, 'GET') end def test_auth_header_iis @expected[3] = 'qop="auth"' assert_equal expected, @da.auth_header(@uri, @header, 'GET', true) end def test_auth_header_no_qop @header.sub! ' qop="auth",', '' @expected[8] = 'response="32f6ca1631ccf7c42a8075deff44e470"' @expected.delete 'qop=auth' @expected.delete 'cnonce="9ea5ff3bd34554a4165bbdc1df91dcff"' @expected.delete 'nc=00000000' assert_equal expected, @da.auth_header(@uri, @header, 'GET') end def test_auth_header_opaque @expected << 'opaque="5ccc069c403ebaf9f0171e9517f40e41"' @header << 'opaque="5ccc069c403ebaf9f0171e9517f40e41"' assert_equal expected, @da.auth_header(@uri, @header, 'GET') end def test_auth_header_post @expected[8] = 'response="d82219e1e5430b136bbae1670fa51d48"' assert_equal expected, @da.auth_header(@uri, @header, 'POST') end def test_auth_header_sess @header << ', algorithm=MD5-sess' @expected[2] = 'algorithm=MD5-sess' @expected[8] = 'response="c22c5bd9112a86ca78ddc1ae772daeeb"' assert_equal expected, @da.auth_header(@uri, @header, 'GET') end def test_auth_header_sha1 @expected[2] = 'algorithm=SHA1' @expected[8] = 'response="2cb62fc18f7b0ebdc34543f896bb7768"' @header << 'algorithm=SHA1' assert_equal expected, @da.auth_header(@uri, @header, 'GET') end def test_auth_header_unknown_algorithm @header << 'algorithm=bogus' e = assert_raises Net::HTTP::DigestAuth::Error do @da.auth_header @uri, @header, 'GET' end assert_equal 'unknown algorithm "bogus"', e.message end def test_auth_header_quoted_algorithm @header << 'algorithm="MD5"' assert_equal expected, @da.auth_header(@uri, @header, 'GET') end def test_make_cnonce da = Net::HTTP::DigestAuth.new cnonce = da.make_cnonce assert_match %r%\A[a-f\d]{32}\z%, cnonce refute_equal cnonce, da.make_cnonce end def test_next_nonce first = @da.next_nonce assert_equal first + 1, @da.next_nonce end end net-http-digest_auth-1.4/Rakefile0000644000004100000410000000072212222370721017113 0ustar www-datawww-data# -*- ruby -*- require 'rubygems' require 'hoe' Hoe.plugin :git Hoe.plugin :minitest Hoe.plugin :travis Hoe.spec 'net-http-digest_auth' do developer 'Eric Hodel', 'drbrain@segment7.net' rdoc_locations << 'docs.seattlerb.org:/data/www/docs.seattlerb.org/net-http-digest_auth/' rdoc_locations << 'rubyforge.org:/var/www/gforge-projects/seattlerb/net-http-digest_auth/' self.spec_extras[:required_ruby_version] = '>= 1.8.7' end # vim: syntax=Ruby net-http-digest_auth-1.4/History.txt0000644000004100000410000000207312222370721017651 0ustar www-datawww-data=== 1.4 / 2013-07-23 * Minor enhancements * Relaxed parser to accept quoted algorithm to work with Linksys SPA922. Pull request #8 by Ismail Hanli, Issue #5 by bearded === 1.3 / 2012-03-28 * Minor enhancements * The cnonce is regenerated for every request to improve security. * SecureRandom is used to generate the cnonce instead of Kernel#rand * Bug fix * cnonce and nonce-count are no longer sent when qop was not provided per RFC 2617 section 3.2.2. === 1.2.1 / 2012-05-18 * Bug fix * Fixed -sess authentication. This also fixes pull request #4 by joe81 === 1.2 / 2011-11-22 * Minor enhancement * Now thread safe. Issue #2 by chrisochs. === 1.1.1 / 2011-04-03 * Bug fix * Fix syntax error on ruby 1.8 === 1.1 / 2011-03-29 * Minor enhancements * Add support for SHA1, SHA2, SHA256, SHA384, SHA512, RMD160 algorithms * Bug fixes * Support opaque per RFC 2617 3.2.1 * Support MD5-sess per RFC 2617 3.2.2.2 * Support unspecified qop for RFC 2069 compatibility per RFC 2617 3.2.2.1 === 1.0 / 2010-09-10 * Major enhancements * Birthday! net-http-digest_auth-1.4/.gemtest0000644000004100000410000000000012222370721017104 0ustar www-datawww-datanet-http-digest_auth-1.4/checksums.yaml.gz0000444000004100000410000000041612222370721020734 0ustar www-datawww-dataiQe;[ADsBhM+E^[<ۯ/8-m˰={& mqx#xilwТnet-http-digest_auth-1.4/metadata.yml0000644000004100000410000000760212222370721017755 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: net-http-digest_auth version: !ruby/object:Gem::Version version: '1.4' platform: ruby authors: - Eric Hodel autorequire: bindir: bin cert_chain: - | -----BEGIN CERTIFICATE----- MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu ZXQwHhcNMTMwMjI4MDUyMjA4WhcNMTQwMjI4MDUyMjA4WjBBMRAwDgYDVQQDDAdk cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76 LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh sCANiQ8BAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW BBS5k4Z75VSpdM0AclG2UvzFA/VW5DAfBgNVHREEGDAWgRRkcmJyYWluQHNlZ21l bnQ3Lm5ldDAfBgNVHRIEGDAWgRRkcmJyYWluQHNlZ21lbnQ3Lm5ldDANBgkqhkiG 9w0BAQUFAAOCAQEAOflo4Md5aJF//EetzXIGZ2EI5PzKWX/mMpp7cxFyDcVPtTv0 js/6zWrWSbd60W9Kn4ch3nYiATFKhisgeYotDDz2/pb/x1ivJn4vEvs9kYKVvbF8 V7MV/O5HDW8Q0pA1SljI6GzcOgejtUMxZCyyyDdbUpyAMdt9UpqTZkZ5z1sicgQk 5o2XJ+OhceOIUVqVh1r6DNY5tLVaGJabtBmJAYFVznDcHiSFybGKBa5n25Egql1t KDyY1VIazVgoC8XvR4h/95/iScPiuglzA+DBG1hip1xScAtw05BrXyUNrc9CEMYU wgF94UVoHRp6ywo8I7NP3HcwFQDFNEZPNGXsng== -----END CERTIFICATE----- date: 2013-07-23 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '5.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '5.0' - !ruby/object:Gem::Dependency name: rdoc requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '4.0' - !ruby/object:Gem::Dependency name: hoe requirement: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '3.6' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - ~> - !ruby/object:Gem::Version version: '3.6' description: |- An implementation of RFC 2617 - Digest Access Authentication. At this time the gem does not drop in to Net::HTTP and can be used for with other HTTP clients. In order to use net-http-digest_auth you'll need to perform some request wrangling on your own. See the class documentation at Net::HTTP::DigestAuth for an example. email: - drbrain@segment7.net executables: [] extensions: [] extra_rdoc_files: - History.txt - Manifest.txt - README.txt files: - .autotest - History.txt - Manifest.txt - README.txt - Rakefile - lib/net/http/digest_auth.rb - sample/auth_server.rb - sample/net_http_example.rb - test/test_net_http_digest_auth.rb - .gemtest homepage: http://github.com/drbrain/net-http-digest_auth licenses: [] metadata: {} post_install_message: rdoc_options: - --main - README.txt require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.8.7 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: net-http-digest_auth rubygems_version: 2.0.4 signing_key: specification_version: 4 summary: An implementation of RFC 2617 - Digest Access Authentication test_files: - test/test_net_http_digest_auth.rb net-http-digest_auth-1.4/metadata.gz.sig0000444000004100000410000000040012222370721020340 0ustar www-datawww-data,RO;*qH%OU+_iP-ȡ%_ =E(J}@cnVzR3X~rjvF]Z ɲ tRA=r$qzWr)OBdcukwȯHVPsÙ4S"0B2.nBW7%<.C<}=^S t68ZRb +c)ȪL5tpYo 2net-http-digest_auth-1.4/Manifest.txt0000644000004100000410000000024612222370721017756 0ustar www-datawww-data.autotest History.txt Manifest.txt README.txt Rakefile lib/net/http/digest_auth.rb sample/auth_server.rb sample/net_http_example.rb test/test_net_http_digest_auth.rb net-http-digest_auth-1.4/data.tar.gz.sig0000444000004100000410000000040012222370721020256 0ustar www-datawww-data䖸'W6vߊ) 85ڋvwTgQ\3Vo,fy.D`*Oa,t)<} v&>Il"V搔H`7эu-n5-aKd|r:N_5nAHK@{bAm#,yc}76yadva(h2Qx } ;:B0MJh6Pnet-http-digest_auth-1.4/.autotest0000644000004100000410000000016612222370721017321 0ustar www-datawww-data# -*- ruby -*- require 'autotest/restart' Autotest.add_hook :initialize do |at| at.testlib = 'minitest/unit' end net-http-digest_auth-1.4/README.txt0000644000004100000410000000317612222370721017152 0ustar www-datawww-data= net-http-digest_auth code :: http://github.com/drbrain/net-http-digest_auth rdoc :: http://docs.seattlerb.org/net-http-digest_auth other :: http://www.rfc-editor.org/rfc/rfc2617.txt == DESCRIPTION: An implementation of RFC 2617 - Digest Access Authentication. At this time the gem does not drop in to Net::HTTP and can be used for with other HTTP clients. In order to use net-http-digest_auth you'll need to perform some request wrangling on your own. See the class documentation at Net::HTTP::DigestAuth for an example. == INSTALL: gem install net-http-digest_auth == LICENSE: (The MIT License) Copyright (c) Eric Hodel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. net-http-digest_auth-1.4/lib/0000755000004100000410000000000012222370721016213 5ustar www-datawww-datanet-http-digest_auth-1.4/lib/net/0000755000004100000410000000000012222370721017001 5ustar www-datawww-datanet-http-digest_auth-1.4/lib/net/http/0000755000004100000410000000000012222370721017760 5ustar www-datawww-datanet-http-digest_auth-1.4/lib/net/http/digest_auth.rb0000644000004100000410000001035712222370721022613 0ustar www-datawww-datarequire 'cgi' require 'digest' require 'monitor' require 'net/http' require 'securerandom' ## # An implementation of RFC 2617 Digest Access Authentication. # # http://www.rfc-editor.org/rfc/rfc2617.txt # # Here is a sample usage of DigestAuth on Net::HTTP: # # require 'uri' # require 'net/http' # require 'net/http/digest_auth' # # digest_auth = Net::HTTP::DigestAuth.new # # uri = URI.parse 'http://localhost:8000/' # uri.user = 'username' # uri.password = 'password' # # h = Net::HTTP.new uri.host, uri.port # # req = Net::HTTP::Get.new uri.request_uri # # res = h.request req # # res is a 401 response with a WWW-Authenticate header # # auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET' # # # create a new request with the Authorization header # req = Net::HTTP::Get.new uri.request_uri # req.add_field 'Authorization', auth # # # re-issue request with Authorization # res = h.request req class Net::HTTP::DigestAuth include MonitorMixin ## # DigestAuth error class class Error < RuntimeError; end ## # Version of Net::HTTP::DigestAuth you are using VERSION = '1.4' ## # Creates a new DigestAuth header creator. def initialize ignored = :ignored mon_initialize @nonce_count = -1 end ## # Creates a digest auth header for +uri+ from the +www_authenticate+ header # for HTTP method +method+. # # The result of this method should be sent along with the HTTP request as # the "Authorization" header. In Net::HTTP this will look like: # # request.add_field 'Authorization', digest_auth.auth_header # ... # # See Net::HTTP::DigestAuth for a complete example. # # IIS servers handle the "qop" parameter of digest authentication # differently so you may need to set +iis+ to true for such servers. def auth_header uri, www_authenticate, method, iis = false nonce_count = next_nonce user = CGI.unescape uri.user password = CGI.unescape uri.password www_authenticate =~ /^(\w+) (.*)/ challenge = $2 params = {} challenge.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 } challenge =~ /algorithm="?(.*?)"?([, ]|$)/ params['algorithm'] = $1 || 'MD5' if params['algorithm'] =~ /(.*?)(-sess)?$/ algorithm = case $1 when 'MD5' then Digest::MD5 when 'SHA1' then Digest::SHA1 when 'SHA2' then Digest::SHA2 when 'SHA256' then Digest::SHA256 when 'SHA384' then Digest::SHA384 when 'SHA512' then Digest::SHA512 when 'RMD160' then Digest::RMD160 else raise Error, "unknown algorithm \"#{$1}\"" end sess = $2 end qop = params['qop'] cnonce = make_cnonce if qop or sess a1 = if sess then [ algorithm.hexdigest("#{user}:#{params['realm']}:#{password}"), params['nonce'], cnonce, ].join ':' else "#{user}:#{params['realm']}:#{password}" end ha1 = algorithm.hexdigest a1 ha2 = algorithm.hexdigest "#{method}:#{uri.request_uri}" request_digest = [ha1, params['nonce']] request_digest.push(('%08x' % nonce_count), cnonce, qop) if qop request_digest << ha2 request_digest = request_digest.join ':' header = [ "Digest username=\"#{user}\"", "realm=\"#{params['realm']}\"", "algorithm=#{params['algorithm']}", if qop.nil? then elsif iis then "qop=\"#{qop}\"" else "qop=#{qop}" end, "uri=\"#{uri.request_uri}\"", "nonce=\"#{params['nonce']}\"", if qop then [ "nc=#{'%08x' % @nonce_count}", "cnonce=\"#{cnonce}\"", ] end, "response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"", if params.key? 'opaque' then "opaque=\"#{params['opaque']}\"" end ].compact header.join ', ' end ## # Creates a client nonce value that is used across all requests based on the # current time, process id and a random number def make_cnonce Digest::MD5.hexdigest [ Time.now.to_i, $$, SecureRandom.random_number(2**32), ].join ':' end def next_nonce synchronize do @nonce_count += 1 end end end