vines-backdoor 0.0.1
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.
- data/.gitignore +18 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +81 -0
- data/Rakefile +3 -0
- data/lib/vines/backdoor.rb +8 -0
- data/lib/vines/backdoor/auth.rb +39 -0
- data/lib/vines/backdoor/bind.rb +35 -0
- data/lib/vines/backdoor/config/port.rb +14 -0
- data/lib/vines/backdoor/gap.rb +44 -0
- data/lib/vines/backdoor/stream/http.rb +35 -0
- data/lib/vines/backdoor/stream/http/start.rb +24 -0
- data/lib/vines/backdoor/version.rb +6 -0
- data/spec/lib/vines/backdoor/auth_spec.rb +67 -0
- data/spec/lib/vines/backdoor/bind_spec.rb +73 -0
- data/spec/lib/vines/backdoor/gap_spec.rb +71 -0
- data/spec/lib/vines/backdoor/stream/http/start_spec.rb +31 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/support/helpers.rb +14 -0
- data/vines-backdoor.gemspec +28 -0
- metadata +153 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Strech (Sergey Fedorov)
|
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,81 @@
|
|
1
|
+
[](https://travis-ci.org/Strech/vines-backdoor)
|
2
|
+
[](https://codeclimate.com/github/Strech/vines-backdoor)
|
3
|
+
|
4
|
+
# Vines::Backdoor
|
5
|
+
|
6
|
+
Allows you to authenticate and generate bosh session for vines user by sigle request without password.
|
7
|
+
|
8
|
+
All that you need – a secret key from backdoor of your vines
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'vines-backdoor'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install vines-backdoor
|
23
|
+
|
24
|
+
## :warning: Attention :warning:
|
25
|
+
|
26
|
+
Never, ever, ever use this for external client authentication. This extension is only for internal server use :fire:
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Modify your vines config file
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
# conf/config.rb
|
34
|
+
|
35
|
+
require 'vines/backdoor'
|
36
|
+
|
37
|
+
# http bind section
|
38
|
+
http '0.0.0.0', 5280 do
|
39
|
+
bind '/http-bind'
|
40
|
+
max_stanza_size 65536
|
41
|
+
max_resources_per_account 5
|
42
|
+
root 'web'
|
43
|
+
vroute ''
|
44
|
+
backdoor 'my-secret-backdoor-key'
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
Now http service accept extended requests with some extra data in it.
|
49
|
+
All response messages (errors and success responses) are RFC compatible
|
50
|
+
|
51
|
+
Send authentication and binding request in a batch
|
52
|
+
|
53
|
+
```html
|
54
|
+
<body xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" xmpp:version="1.0"
|
55
|
+
content="text/xml; charset=utf-8" rid="235205804" to="localhost" secure="true" wait="60" hold="1"
|
56
|
+
backdoor="my-secret-backdoor-key">
|
57
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL">user@localhost</auth>
|
58
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
59
|
+
<resource>pidgin</resource>
|
60
|
+
</bind>
|
61
|
+
</body>
|
62
|
+
```
|
63
|
+
|
64
|
+
And get a successful response
|
65
|
+
|
66
|
+
```html
|
67
|
+
<iq type="result" id="235205804">
|
68
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
69
|
+
<jid>user@localhost/pidgin</jid>
|
70
|
+
<sid>f27c71df-f124-4829-b415-5855b8c04109</sid>
|
71
|
+
</bind>
|
72
|
+
</iq>
|
73
|
+
```
|
74
|
+
|
75
|
+
## Contributing
|
76
|
+
|
77
|
+
1. Fork it ( http://github.com/Strech/vines-backdoor/fork )
|
78
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
79
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
80
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
81
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "vines/backdoor/version"
|
3
|
+
require "vines/backdoor/gap"
|
4
|
+
require "vines/backdoor/bind"
|
5
|
+
require "vines/backdoor/auth"
|
6
|
+
require "vines/backdoor/config/port"
|
7
|
+
require "vines/backdoor/stream/http"
|
8
|
+
require "vines/backdoor/stream/http/start"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
module Vines
|
3
|
+
module Backdoor
|
4
|
+
class Auth < Vines::Stream::Client::Auth
|
5
|
+
INTERNAL = "INTERNAL".freeze
|
6
|
+
|
7
|
+
def auth(node)
|
8
|
+
raise StreamErrors::NotAuthorized unless auth?(node)
|
9
|
+
|
10
|
+
node = node.xpath('ns:auth', 'ns' => NS).first
|
11
|
+
|
12
|
+
if node.text.empty?
|
13
|
+
send_auth_fail(SaslErrors::MalformedRequest.new)
|
14
|
+
elsif stream.authentication_mechanisms.include?(node[MECHANISM])
|
15
|
+
if node[MECHANISM] == INTERNAL
|
16
|
+
stream.user = authenticate(node.text) or raise StreamErrors::NotAuthorized
|
17
|
+
end
|
18
|
+
else
|
19
|
+
send_auth_fail(SaslErrors::InvalidMechanism.new)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def auth?(node)
|
25
|
+
node.xpath('ns:auth', 'ns' => NS).any?
|
26
|
+
end
|
27
|
+
|
28
|
+
def authenticate(jid)
|
29
|
+
log.info("Authenticating user: %s" % jid)
|
30
|
+
stream.storage.find_user(jid).tap do |user|
|
31
|
+
log.info("Authentication succeeded (backdoor): %s" % user.jid) if user
|
32
|
+
end
|
33
|
+
rescue => e
|
34
|
+
log.error("Failed to authenticate: #{e.to_s}")
|
35
|
+
raise Vines::SaslErrors::TemporaryAuthFailure
|
36
|
+
end
|
37
|
+
end # class Auth
|
38
|
+
end # module Backdoor
|
39
|
+
end # module Vines
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
module Vines
|
3
|
+
module Backdoor
|
4
|
+
class Bind < Vines::Stream::Client::Bind
|
5
|
+
def bind(node)
|
6
|
+
@attempts += 1
|
7
|
+
raise StreamErrors::NotAuthorized unless bind?(node)
|
8
|
+
raise StreamErrors::PolicyViolation.new('max bind attempts reached') if @attempts > MAX_ATTEMPTS
|
9
|
+
raise StanzaErrors::ResourceConstraint.new(fabricate_request(node), 'wait') if resource_limit_reached?
|
10
|
+
|
11
|
+
stream.bind!(resource(node))
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def bind?(node)
|
16
|
+
node.xpath('ns:bind', 'ns' => NS).any?
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource(node)
|
20
|
+
el = node.xpath('ns:bind/ns:resource', 'ns' => NS).first
|
21
|
+
resource = el ? el.text.strip : ''
|
22
|
+
generate = resource.empty? || !resource_valid?(resource) || resource_used?(resource)
|
23
|
+
generate ? Vines::Kit.uuid : resource
|
24
|
+
end
|
25
|
+
|
26
|
+
def fabricate_request(node)
|
27
|
+
doc = Document.new
|
28
|
+
doc.create_element('iq') do |el|
|
29
|
+
el['id'] = node['rid']
|
30
|
+
el << node.xpath('ns:bind/ns:resource', 'ns' => NS).first
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end # class Bind
|
34
|
+
end # module Backdoor
|
35
|
+
end # module Vines
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Vines
|
3
|
+
class Config
|
4
|
+
class HttpPort
|
5
|
+
def backdoor(secret_key = nil)
|
6
|
+
if secret_key
|
7
|
+
@settings[:backdoor_secret_key] = secret_key
|
8
|
+
else
|
9
|
+
@settings[:backdoor_secret_key]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end # class HttpPort
|
13
|
+
end # class Config
|
14
|
+
end # module Vines
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "nokogiri"
|
3
|
+
|
4
|
+
module Vines
|
5
|
+
module Backdoor
|
6
|
+
class Gap
|
7
|
+
BACKDOOR = "backdoor".freeze
|
8
|
+
|
9
|
+
attr_reader :stream
|
10
|
+
|
11
|
+
def initialize(stream)
|
12
|
+
@stream = stream
|
13
|
+
end
|
14
|
+
|
15
|
+
def node(node)
|
16
|
+
raise StreamErrors::NotAuthorized unless backdoor?(node)
|
17
|
+
|
18
|
+
stream.start_session(node)
|
19
|
+
Backdoor::Auth.new(stream).auth(node)
|
20
|
+
Backdoor::Bind.new(stream).bind(node)
|
21
|
+
|
22
|
+
advance(node)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def advance(node)
|
27
|
+
doc = Nokogiri::XML::Document.new
|
28
|
+
result = doc.create_element('iq', 'id' => node['rid'], 'type' => 'result') do |el|
|
29
|
+
el << doc.create_element('bind') do |bind|
|
30
|
+
bind.default_namespace = Vines::Stream::Client::Bind::NS
|
31
|
+
bind << doc.create_element('jid', stream.user.jid.to_s)
|
32
|
+
bind << doc.create_element('sid', stream.id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
stream.write(result)
|
37
|
+
end
|
38
|
+
|
39
|
+
def backdoor?(node)
|
40
|
+
node[BACKDOOR] && node[BACKDOOR] == @stream.backdoor
|
41
|
+
end
|
42
|
+
end # class Gap
|
43
|
+
end # module Backdoor
|
44
|
+
end # module Vines
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Vines
|
3
|
+
class Stream
|
4
|
+
class Http < Client
|
5
|
+
MECHANISMS = %w[PLAIN INTERNAL].freeze
|
6
|
+
|
7
|
+
def backdoor(*args)
|
8
|
+
config[:http].backdoor(*args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def authentication_mechanisms
|
12
|
+
MECHANISMS
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_session(node)
|
16
|
+
domain, type, hold, wait, rid = %w[to content hold wait rid].map {|a| (node[a] || '').strip }
|
17
|
+
version = node.attribute_with_ns('version', NAMESPACES[:bosh]).value rescue nil
|
18
|
+
|
19
|
+
@session.inactivity = 20
|
20
|
+
@session.domain = domain
|
21
|
+
@session.content_type = type unless type.empty?
|
22
|
+
@session.hold = hold.to_i unless hold.empty?
|
23
|
+
@session.wait = wait.to_i unless wait.empty?
|
24
|
+
|
25
|
+
raise StreamErrors::UndefinedCondition.new('rid required') if rid.empty?
|
26
|
+
raise StreamErrors::UnsupportedVersion unless version == '1.0'
|
27
|
+
raise StreamErrors::ImproperAddressing unless valid_address?(domain)
|
28
|
+
raise StreamErrors::HostUnknown unless config.vhost?(domain)
|
29
|
+
raise StreamErrors::InvalidNamespace unless node.namespaces['xmlns'] == NAMESPACES[:http_bind]
|
30
|
+
|
31
|
+
Sessions[@session.id] = @session
|
32
|
+
end
|
33
|
+
end # class Http
|
34
|
+
end # class Stream
|
35
|
+
end # module Vines
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
module Vines
|
3
|
+
class Stream
|
4
|
+
class Http
|
5
|
+
class Start < State
|
6
|
+
def node(node)
|
7
|
+
raise StreamErrors::NotAuthorized unless body?(node)
|
8
|
+
if session = Sessions[node['sid']]
|
9
|
+
session.resume(stream, node)
|
10
|
+
else
|
11
|
+
|
12
|
+
if node['backdoor']
|
13
|
+
backdoor = Vines::Backdoor::Gap.new(stream)
|
14
|
+
backdoor.node(node)
|
15
|
+
else
|
16
|
+
stream.start(node)
|
17
|
+
advance
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end # class Start
|
22
|
+
end # class Http
|
23
|
+
end # class Stream
|
24
|
+
end # module Vines
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Vines::Backdoor::Auth do
|
5
|
+
let(:klass) { described_class.new(stream) }
|
6
|
+
let(:storage) { double("Storage") }
|
7
|
+
let(:stream) do
|
8
|
+
double("Stream", storage: storage,
|
9
|
+
authentication_mechanisms: ["INTERNAL"]).as_null_object
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when missing auth namespace" do
|
13
|
+
let(:xml) { node(%q{<body><auth mechanism="INTERNAL">user@localhost</auth></body>}) }
|
14
|
+
|
15
|
+
it { expect { klass.auth(xml) }.to raise_error Vines::StreamErrors::NotAuthorized }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when used unknown mechanism" do
|
19
|
+
let(:xml) do
|
20
|
+
node(%q{<body>
|
21
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="FOO">user@localhost</auth>
|
22
|
+
</body>})
|
23
|
+
end
|
24
|
+
|
25
|
+
after { klass.auth(xml) }
|
26
|
+
|
27
|
+
it { expect(stream).to receive(:error).with(kind_of Vines::SaslErrors::InvalidMechanism) }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when no username is given" do
|
31
|
+
let(:xml) do
|
32
|
+
node(%q{<body>
|
33
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL"></auth>
|
34
|
+
</body>})
|
35
|
+
end
|
36
|
+
|
37
|
+
after { klass.auth(xml) }
|
38
|
+
|
39
|
+
it { expect(stream).to receive(:error).with(kind_of Vines::SaslErrors::MalformedRequest) }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when user not found" do
|
43
|
+
let(:xml) do
|
44
|
+
node(%q{<body>
|
45
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL">user@localhost</auth>
|
46
|
+
</body>})
|
47
|
+
end
|
48
|
+
|
49
|
+
before { storage.stub(:find_user).with("user@localhost").and_return nil }
|
50
|
+
|
51
|
+
it { expect { klass.auth(xml) }.to raise_error Vines::StreamErrors::NotAuthorized }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when user is authenticated" do
|
55
|
+
let(:user) { double("User", jid: "user@localhost") }
|
56
|
+
let(:xml) do
|
57
|
+
node(%q{<body>
|
58
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL">user@localhost</auth>
|
59
|
+
</body>})
|
60
|
+
end
|
61
|
+
|
62
|
+
before { storage.stub(:find_user).with("user@localhost").and_return user }
|
63
|
+
after { klass.auth(xml) }
|
64
|
+
|
65
|
+
it { expect(stream).to receive(:user=).with(user) }
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Vines::Backdoor::Bind do
|
5
|
+
let(:klass) { described_class.new(stream) }
|
6
|
+
let(:storage) { double("Storage") }
|
7
|
+
let(:stream) { double("Stream", storage: storage) }
|
8
|
+
|
9
|
+
context "when missing bind namespace" do
|
10
|
+
let(:xml) { node(%q{<body><bind><resource>pidgin</resource></bind></body>}) }
|
11
|
+
|
12
|
+
it { expect { klass.bind(xml) }.to raise_error Vines::StreamErrors::NotAuthorized }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when max attemps is reached" do
|
16
|
+
let(:xml) do
|
17
|
+
node(%q{<body>
|
18
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
19
|
+
<resource>pidgin</resource>
|
20
|
+
</bind></body>})
|
21
|
+
end
|
22
|
+
|
23
|
+
before { stub_const("Vines::Stream::Client::Bind::MAX_ATTEMPTS", 0) }
|
24
|
+
|
25
|
+
it { expect { klass.bind(xml) }.to raise_error Vines::StreamErrors::PolicyViolation }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when resource limit is reached" do
|
29
|
+
let(:xml) do
|
30
|
+
node(%q{<body>
|
31
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
32
|
+
<resource>pidgin</resource>
|
33
|
+
</bind></body>})
|
34
|
+
end
|
35
|
+
|
36
|
+
before { klass.stub(resource_limit_reached?: true) }
|
37
|
+
|
38
|
+
it { expect { klass.bind(xml) }.to raise_error Vines::StanzaErrors::ResourceConstraint }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when bind session with given resource" do
|
42
|
+
let(:xml) do
|
43
|
+
node(%q{<body>
|
44
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
45
|
+
<resource>pidgin</resource>
|
46
|
+
</bind></body>})
|
47
|
+
end
|
48
|
+
|
49
|
+
before do
|
50
|
+
klass.stub(resource_valid?: true)
|
51
|
+
klass.stub(resource_limit_reached?: false)
|
52
|
+
klass.stub(:resource_used?).with("pidgin").and_return false
|
53
|
+
end
|
54
|
+
after { klass.bind(xml) }
|
55
|
+
|
56
|
+
it { expect(stream).to receive(:bind!).with("pidgin") }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when bind session with generated resource" do
|
60
|
+
let(:xml) { node(%q{<body><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></body>}) }
|
61
|
+
|
62
|
+
before do
|
63
|
+
klass.stub(resource_valid?: true)
|
64
|
+
klass.stub(resource_limit_reached?: false)
|
65
|
+
end
|
66
|
+
after { klass.bind(xml) }
|
67
|
+
|
68
|
+
it do
|
69
|
+
expect(Vines::Kit).to receive(:uuid).and_return "random-resource"
|
70
|
+
expect(stream).to receive(:bind!).with("random-resource")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Vines::Backdoor::Gap do
|
5
|
+
let(:klass) { described_class.new(stream) }
|
6
|
+
let(:storage) { double("Storage") }
|
7
|
+
let(:stream) { double("Stream", storage: storage).as_null_object }
|
8
|
+
|
9
|
+
context "when backdoor attribute is missing" do
|
10
|
+
let(:xml) do
|
11
|
+
node(%q{<body>
|
12
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL">user@localhost</auth>
|
13
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
14
|
+
<resource>pidgin</resource>
|
15
|
+
</bind></body>})
|
16
|
+
end
|
17
|
+
|
18
|
+
it { expect { klass.node(xml) }.to raise_error Vines::StreamErrors::NotAuthorized }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when backdoor attribute is wrong" do
|
22
|
+
let(:xml) do
|
23
|
+
node(%q{<body backdoor="12345">
|
24
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL">user@localhost</auth>
|
25
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
26
|
+
<resource>pidgin</resource>
|
27
|
+
</bind></body>})
|
28
|
+
end
|
29
|
+
|
30
|
+
before { stream.stub(backdoor: 9000) }
|
31
|
+
|
32
|
+
it { expect { klass.node(xml) }.to raise_error Vines::StreamErrors::NotAuthorized }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when user is authenticated and session is binded" do
|
36
|
+
let(:user) { double("User", jid: "user@localhost/pidgin") }
|
37
|
+
let(:xml) do
|
38
|
+
node(%q{<body rid="100500" backdoor="9000">
|
39
|
+
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="INTERNAL">user@localhost</auth>
|
40
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
41
|
+
<resource>pidgin</resource>
|
42
|
+
</bind></body>})
|
43
|
+
end
|
44
|
+
let(:expected) do
|
45
|
+
node(%q{<iq id="100500" type="result">
|
46
|
+
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
47
|
+
<jid>user@localhost/pidgin</jid>
|
48
|
+
<sid>abcde-12345-fghijk-6789-xyz</sid>
|
49
|
+
</bind></iq>})
|
50
|
+
end
|
51
|
+
|
52
|
+
before do
|
53
|
+
stream.stub(backdoor: "9000")
|
54
|
+
stream.stub(authentication_mechanisms: ["INTERNAL"])
|
55
|
+
stream.stub(user: user)
|
56
|
+
stream.stub(id: "abcde-12345-fghijk-6789-xyz")
|
57
|
+
|
58
|
+
storage.stub(:find_user).with("user@localhost").and_return user
|
59
|
+
|
60
|
+
Vines::Backdoor::Bind.any_instance.stub(resource_valid?: true)
|
61
|
+
Vines::Backdoor::Bind.any_instance.stub(resource_limit_reached?: false)
|
62
|
+
end
|
63
|
+
after { klass.node(xml) }
|
64
|
+
|
65
|
+
it do
|
66
|
+
expect(stream).to receive(:write) do |response|
|
67
|
+
expect(response.to_s).to eq expected.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Vines::Stream::Http::Start do
|
5
|
+
context "when backdoor attribute present" do
|
6
|
+
let(:start) { described_class.new(stream) }
|
7
|
+
let(:xml) { node(%q{<body xmlns="http://jabber.org/protocol/httpbind" rid="42" backdoor="12345"/>}) }
|
8
|
+
let(:gap) { double("Backdoor gap").as_null_object }
|
9
|
+
let(:stream) { double("Stream", backdoor: "12345") }
|
10
|
+
|
11
|
+
after { em { start.node(xml) } }
|
12
|
+
|
13
|
+
it do
|
14
|
+
expect(Vines::Backdoor::Gap).to receive(:new).with(stream).and_return gap
|
15
|
+
expect(gap).to receive(:node).with(xml)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when backdoor attribute is missing" do
|
20
|
+
let(:start) { described_class.new(stream) }
|
21
|
+
let(:xml) { node(%q{<body xmlns="http://jabber.org/protocol/httpbind" rid="42" />}) }
|
22
|
+
let(:stream) { double("Stream", backdoor: "12345") }
|
23
|
+
|
24
|
+
after { em { start.node(xml) } }
|
25
|
+
|
26
|
+
it do
|
27
|
+
expect(stream).to receive(:start).with(xml)
|
28
|
+
expect(stream).to receive(:advance)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
if ENV["COV"]
|
3
|
+
require "simplecov"
|
4
|
+
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "/spec/"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require "vines"
|
11
|
+
require "vines/backdoor"
|
12
|
+
|
13
|
+
# Disable vines logger
|
14
|
+
Class.new.extend(Vines::Log).log.level = Logger::FATAL
|
15
|
+
Dir[File.join(File.dirname(__FILE__), 'support', '**', '*.rb')].each { |file| require file }
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.formatter = :progress
|
19
|
+
config.order = :random
|
20
|
+
config.color = true
|
21
|
+
|
22
|
+
include Helpers
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "vines/backdoor/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "vines-backdoor"
|
9
|
+
spec.version = Vines::Backdoor::VERSION
|
10
|
+
spec.authors = ["Strech (Sergey Fedorov)"]
|
11
|
+
spec.email = ["strech_ftf@mail.ru"]
|
12
|
+
spec.summary = "Accelerated http-bind session creation"
|
13
|
+
spec.description = "XMPP protocol extension for Vines server"
|
14
|
+
spec.homepage = "https://github.com/Strech/vines-backdoor"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "vines", ">= 0.4.5"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
25
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
26
|
+
spec.add_development_dependency "simplecov"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vines-backdoor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Strech (Sergey Fedorov)
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-02-20 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: vines
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.4.5
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ! '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.4.5
|
28
|
+
type: :runtime
|
29
|
+
prerelease: false
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.5'
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.5'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.14'
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.14'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: simplecov
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
description: XMPP protocol extension for Vines server
|
95
|
+
email:
|
96
|
+
- strech_ftf@mail.ru
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .travis.yml
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/vines/backdoor.rb
|
108
|
+
- lib/vines/backdoor/auth.rb
|
109
|
+
- lib/vines/backdoor/bind.rb
|
110
|
+
- lib/vines/backdoor/config/port.rb
|
111
|
+
- lib/vines/backdoor/gap.rb
|
112
|
+
- lib/vines/backdoor/stream/http.rb
|
113
|
+
- lib/vines/backdoor/stream/http/start.rb
|
114
|
+
- lib/vines/backdoor/version.rb
|
115
|
+
- spec/lib/vines/backdoor/auth_spec.rb
|
116
|
+
- spec/lib/vines/backdoor/bind_spec.rb
|
117
|
+
- spec/lib/vines/backdoor/gap_spec.rb
|
118
|
+
- spec/lib/vines/backdoor/stream/http/start_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
- spec/support/helpers.rb
|
121
|
+
- vines-backdoor.gemspec
|
122
|
+
homepage: https://github.com/Strech/vines-backdoor
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.8.25
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Accelerated http-bind session creation
|
147
|
+
test_files:
|
148
|
+
- spec/lib/vines/backdoor/auth_spec.rb
|
149
|
+
- spec/lib/vines/backdoor/bind_spec.rb
|
150
|
+
- spec/lib/vines/backdoor/gap_spec.rb
|
151
|
+
- spec/lib/vines/backdoor/stream/http/start_spec.rb
|
152
|
+
- spec/spec_helper.rb
|
153
|
+
- spec/support/helpers.rb
|