sip_digest_auth 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTY0YjU1NTExNzI0ZTA2NjBmZDFkZjI3NmRmZjYyOTQ1MjY0NWUxNw==
5
+ data.tar.gz: !binary |-
6
+ ZTMzNDY4MjIxYzhmYjZlZTA2MzY2YjcyMzM3NmQ2ZjgxOTkzNDVlMw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NjU0YjljMjUyYjFmNTk0OWJkODY5YjNiMjc0MTViMzIzOGM1MWFkOGZjOTVm
10
+ MDYzNDA4NjY3MjI5NzJhM2ZhNWQ3MTYzYWVlNWU0YzBhMzAxOTViMTY1NmJh
11
+ ZTIzM2M5NTE1NzNmNmQ4NzNkOGNlNTQ5MWM5NDYwMWQ2YmVmM2Y=
12
+ data.tar.gz: !binary |-
13
+ ZDIwOTNhODdhYTFiZGY2MTlkYjhjNjVhYWU2Y2Q0MGU3MTdjMTgzYzhlZGM2
14
+ Y2JiYmI3MzAxMTQwZTMwYWJmMWE3YmFjZjM5YjE3MWIxM2JkNzc4MjhjZGVj
15
+ MGJlZTE4OTZkMGMwZjVkNWJkNTRlNTVmODdjNDAyOGFhYjIwOGQ=
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .ruby-version
19
+ /.idea
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sip_digest_auth.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Daniel Jabbour
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # SipDigestAuth
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'sip_digest_auth'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install sip_digest_auth
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/*.rb'
7
+ end
@@ -0,0 +1,38 @@
1
+ require 'sip_digest_auth/util'
2
+ require 'sip_digest_auth/session'
3
+ require 'sip_digest_auth/version'
4
+
5
+ module SipDigestAuth
6
+ extend self
7
+
8
+ def challenge(session)
9
+ header_name = session.proxy ? 'proxy-authenticate' : 'www-authenticate'
10
+
11
+ header_values = [
12
+ "Digest",
13
+ "realm: #{q(session.realm)}",
14
+ "qop: #{q(session.qop)}",
15
+ "algorithm: #{q(session.algorithm)}",
16
+ "nonce: #{q(session.nonce)}",
17
+ "opaque: #{q(session.opaque)}"
18
+ ]
19
+
20
+ [header_name, header_values.join(', ')]
21
+ end
22
+
23
+ # Credentials are optional if the session is established. When specified, it is a hash containing
24
+ # either :user & :password OR the key :hash. Required on the first call to cache h1 in session.
25
+ def authenticate_request(session, request, credentials=nil)
26
+ #TODO: Implement
27
+ end
28
+
29
+ protected
30
+
31
+ def q(str)
32
+ if str && str[0] != '"'
33
+ str = "\"#{str}\""
34
+ end
35
+ str
36
+ end
37
+
38
+ end
@@ -0,0 +1,35 @@
1
+ require 'hashie/dash'
2
+
3
+ module SipDigestAuth
4
+ class Session < ::Hashie::Dash
5
+ # Realm *must* be set, and is the only required field when creating a session for the first time
6
+ property :realm, required: true
7
+
8
+ # The nonce should stay the same for a single session, and will be generated if not provided on
9
+ # initialization. Subsequent requests within the same session should ensure nonce is set
10
+ property :nonce, default: Util.generate_nonce
11
+
12
+ # Opaque doesn't seem to be mandated and I'm a little confused as to why it's necessary with a
13
+ # nonce. Rfc2617 specifies: "A string of data, specified by the server, which should be returned
14
+ # by the client unchanged in the Authorization header of subsequent requests with URIs in the
15
+ # same protection space." In this case, I'm going to leave it up to the caller to specify it.
16
+ property :opaque, default: ''
17
+
18
+ # The ha1 is generated during authentication. HA1 = MD5(username:realm:password)
19
+ property :ha1
20
+
21
+ # When true, assume a proxy of some kind to an upstream SIP provider. This has subtle effects on
22
+ # how authentication takes place (for example, changing the name of the challenge headers)
23
+ property :proxy, default: false
24
+
25
+ # These are internal and probably not going to change, but it's possible to build more support
26
+ # into the library later, and they really belong in the session:
27
+ property :qop, default: 'auth,auth-int'
28
+ property :algorithm, default: 'md5'
29
+ property :nc, default: 0
30
+
31
+ def increment_nc!
32
+ self.nc = self.nc + 1
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ require 'base64'
2
+
3
+ module SipDigestAuth
4
+ # Utility functions for our library
5
+ module Util
6
+ extend self
7
+
8
+ # args is an array of crap
9
+ def create_digest(*args)
10
+ ::Digest::MD5.hexdigest(args.join(":"))
11
+ end
12
+
13
+ def generate_nonce(secret_key = rand.to_s, time = Time.now)
14
+ t = time.to_i
15
+ create_digest(t, secret_key)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module SipDigestAuth
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sip_digest_auth/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sip_digest_auth"
8
+ spec.version = SipDigestAuth::VERSION
9
+ spec.authors = ["Daniel Jabbour"]
10
+ spec.email = ["sayhi@amoe.ba"]
11
+ spec.description = "Implementation of SIP Digest Authentication as specified in RFC3261"
12
+ spec.summary = "This gem is to be used with a SIP server to implement Digest Authentication, like HTTP authentication (specified in RFC2617)"
13
+ spec.homepage = "http://github.com/AmoebaLabs/sip_digest_auth"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "hashie"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "minitest", "~> 5.2.0"
26
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe SipDigestAuth::Session do
4
+ before do
5
+ @session = SipDigestAuth::Session.new(realm: "test")
6
+ end
7
+
8
+ it "lets you pass all arguments on initializer" do
9
+ session = SipDigestAuth::Session.new({
10
+ realm: 'test',
11
+ nonce: 'test',
12
+ opaque: 'test',
13
+ ha1: 'test',
14
+ proxy: true
15
+ })
16
+
17
+ %w(realm nonce opaque ha1).each do |field|
18
+ session.send(field).must_equal 'test'
19
+ end
20
+ session.proxy.must_equal true
21
+ end
22
+
23
+ it "requires a realm" do
24
+ proc {
25
+ session = SipDigestAuth::Session.new
26
+ }.must_raise ArgumentError
27
+ end
28
+
29
+ it "has a nonce by default" do
30
+ @session.nonce.wont_be_empty
31
+ end
32
+
33
+ it "has a blank opaque by default" do
34
+ @session.opaque.must_be_empty
35
+ end
36
+
37
+ it "has no default ha1" do
38
+ @session.ha1.must_be_nil
39
+ end
40
+
41
+ it "lets you set a ha1" do
42
+ @session.ha1 = "test"
43
+ @session.ha1.must_equal "test"
44
+ end
45
+
46
+ it "defaults to no proxy mode" do
47
+ @session.proxy.must_equal false
48
+ end
49
+
50
+ it "lets you set the proxy" do
51
+ @session.proxy = true
52
+ @session.proxy.must_equal true
53
+ end
54
+
55
+ it "deafults qop properly" do
56
+ @session.qop.must_equal 'auth,auth-int'
57
+ end
58
+
59
+ it "defaults algorithm property" do
60
+ @session.algorithm.must_equal 'md5'
61
+ end
62
+
63
+ it "has a nc of 0 by default" do
64
+ @session.nc.must_equal 0
65
+ end
66
+
67
+ it "can increment nc" do
68
+ nc = @session.nc
69
+ @session.increment_nc!
70
+ @session.nc.must_equal nc+1
71
+ end
72
+
73
+
74
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ require 'base64'
4
+
5
+ describe SipDigestAuth::Util do
6
+ describe "#create_digest" do
7
+ it "can make a digest with arguments" do
8
+ args = ['1', '2']
9
+ SipDigestAuth::Util.create_digest(*args).must_equal ::Digest::MD5.hexdigest(args.join(":"))
10
+ end
11
+
12
+ it "can make a digest with an array" do
13
+ args = ['1', '2']
14
+ SipDigestAuth::Util.create_digest(args).must_equal ::Digest::MD5.hexdigest(args.join(":"))
15
+ end
16
+ end
17
+
18
+ describe "#generate_nonce" do
19
+ it "generates a 32 character string" do
20
+ SipDigestAuth::Util.generate_nonce.length.must_equal 32
21
+ end
22
+
23
+ it "lets you specify the secret_key and time" do
24
+ time = Time.now
25
+ nonce = SipDigestAuth::Util.generate_nonce("secret", time)
26
+ nonce.must_equal SipDigestAuth::Util.create_digest(time.to_i, "secret")
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe SipDigestAuth do
4
+ describe "#challenge" do
5
+ before do
6
+ @session = SipDigestAuth::Session.new(realm: 'test', qop: 'test', algorithm: 'test', nonce: 'test', opaque: '')
7
+ end
8
+
9
+ it "returns proxy-authenticate when session.proxy" do
10
+ @session.proxy = true
11
+ SipDigestAuth.challenge(@session)[0].must_equal 'proxy-authenticate'
12
+ end
13
+
14
+ it "returns www-authenticate when not session.proxy" do
15
+ @session.proxy = false
16
+ SipDigestAuth.challenge(@session)[0].must_equal 'www-authenticate'
17
+ end
18
+
19
+ it "contains the accurate session values in its return header" do
20
+ SipDigestAuth.challenge(@session)[1].must_equal [
21
+ 'Digest',
22
+ "realm: \"#{@session.realm}\"",
23
+ "qop: \"#{@session.qop}\"",
24
+ "algorithm: \"#{@session.algorithm}\"",
25
+ "nonce: \"#{@session.nonce}\"",
26
+ "opaque: \"#{@session.opaque}\""
27
+ ].join(', ')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,2 @@
1
+ require 'minitest/autorun'
2
+ require 'sip_digest_auth'
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sip_digest_auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Jabbour
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hashie
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 5.2.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 5.2.0
69
+ description: Implementation of SIP Digest Authentication as specified in RFC3261
70
+ email:
71
+ - sayhi@amoe.ba
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/sip_digest_auth.rb
82
+ - lib/sip_digest_auth/session.rb
83
+ - lib/sip_digest_auth/util.rb
84
+ - lib/sip_digest_auth/version.rb
85
+ - sip_digest_auth.gemspec
86
+ - test/sip_digest_auth/session_spec.rb
87
+ - test/sip_digest_auth/util_spec.rb
88
+ - test/sip_digest_auth_spec.rb
89
+ - test/spec_helper.rb
90
+ homepage: http://github.com/AmoebaLabs/sip_digest_auth
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.1
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: This gem is to be used with a SIP server to implement Digest Authentication,
114
+ like HTTP authentication (specified in RFC2617)
115
+ test_files:
116
+ - test/sip_digest_auth/session_spec.rb
117
+ - test/sip_digest_auth/util_spec.rb
118
+ - test/sip_digest_auth_spec.rb
119
+ - test/spec_helper.rb