vines 0.4.7 → 0.4.8

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8a283e328bc02906cb090b08bcdc5c5bbc954a93
4
+ data.tar.gz: 37528ba4506f7a6bf6f57a569696eb80e7eed6d1
5
+ SHA512:
6
+ metadata.gz: 16915f6f177f20dd6311d6d57df91bf3981382f38d3ab50d94979d8813db203a20d027e6bde673d5086a637b6db4f140c324d2519866dcd2d8476d79e1d86393
7
+ data.tar.gz: 7cbf9026d98a8d1452af15ffecf2d7544222086fbb0a11ee9ba2e965c0644feefb163dd2e6ea77e0bab881e9b3c724de46eeb3251dbe90d3c3d0b8ed1177e3d6
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2012 Negative Code
1
+ Copyright (c) 2010-2013 Negative Code
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/bin/vines CHANGED
@@ -1,104 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
2
 
4
- require 'optparse'
5
3
  require 'vines'
6
-
7
- COMMANDS = %w[start stop restart init bcrypt cert ldap schema]
8
-
9
- def register_storage
10
- %w[couchdb mongodb redis sql].each do |backend|
11
- begin
12
- require 'vines/storage/%s' % backend
13
- rescue LoadError
14
- # do nothing
15
- end
16
- end
17
- end
18
-
19
- def parse(args)
20
- options = {}
21
- parser = OptionParser.new do |opts|
22
- opts.banner = "Usage: vines [options] #{COMMANDS.join('|')}"
23
-
24
- opts.separator ""
25
- opts.separator "Daemon options:"
26
-
27
- opts.on('-d', '--daemonize', 'Run daemonized in the background') do |daemonize|
28
- options[:daemonize] = daemonize
29
- end
30
-
31
- options[:log] = 'log/vines.log'
32
- opts.on('-l', '--log FILE', 'File to redirect output (default: log/vines.log)') do |log|
33
- options[:log] = log
34
- end
35
-
36
- options[:pid] = 'pid/vines.pid'
37
- opts.on('-P', '--pid FILE', 'File to store PID (default: pid/vines.pid)') do |pid|
38
- options[:pid] = pid
39
- end
40
-
41
- opts.separator ""
42
- opts.separator "Common options:"
43
-
44
- opts.on('-h', '--help', 'Show this message') do |help|
45
- options[:help] = help
46
- end
47
-
48
- opts.on('-v', '--version', 'Show version') do |version|
49
- options[:version] = version
50
- end
51
- end
52
-
53
- begin
54
- parser.parse!(args)
55
- rescue
56
- puts parser
57
- exit(1)
58
- end
59
-
60
- if options[:version]
61
- puts Vines::VERSION
62
- exit
63
- end
64
-
65
- if options[:help]
66
- puts parser
67
- exit
68
- end
69
-
70
- command = args.shift
71
- unless COMMANDS.include?(command)
72
- puts parser
73
- exit(1)
74
- end
75
-
76
- options.tap do |opts|
77
- opts[:args] = args
78
- opts[:command] = command
79
- opts[:config] = File.expand_path('conf/config.rb')
80
- opts[:pid] = File.expand_path(opts[:pid])
81
- opts[:log] = File.expand_path(opts[:log])
82
- end
83
- end
84
-
85
- def check_config(opts)
86
- return if %w[bcrypt init].include?(opts[:command])
87
- unless File.exists?(opts[:config])
88
- puts "No config file found at #{opts[:config]}"
89
- exit(1)
90
- end
91
- end
92
-
93
- register_storage
94
- opts = parse(ARGV)
95
- check_config(opts)
96
- command = Vines::Command.const_get(opts[:command].capitalize).new
97
- begin
98
- command.run(opts)
99
- rescue SystemExit
100
- # do nothing
101
- rescue Exception => e
102
- puts e.message
103
- exit(1)
104
- end
4
+ Vines::CLI.start
@@ -68,11 +68,13 @@ end
68
68
  net/ldap
69
69
  nokogiri
70
70
  openssl
71
+ optparse
71
72
  resolv
72
73
  set
73
74
  socket
74
75
  yaml
75
76
 
77
+ vines/cli
76
78
  vines/log
77
79
  vines/jid
78
80
 
@@ -0,0 +1,132 @@
1
+ module Vines
2
+ # The command line application that's invoked by the `vines` binary included
3
+ # in the gem. Parses the command line arguments to create a new server
4
+ # directory, and starts and stops the server.
5
+ class CLI
6
+ COMMANDS = %w[start stop restart init bcrypt cert ldap schema]
7
+
8
+ def self.start
9
+ self.new.start
10
+ end
11
+
12
+ # Run the command line application to parse arguments and run sub-commands.
13
+ # Exits the process with a non-zero return code to indicate failure.
14
+ #
15
+ # Returns nothing.
16
+ def start
17
+ register_storage
18
+ opts = parse(ARGV)
19
+ check_config(opts)
20
+ command = Command.const_get(opts[:command].capitalize).new
21
+ begin
22
+ command.run(opts)
23
+ rescue SystemExit
24
+ # do nothing
25
+ rescue Exception => e
26
+ puts e.message
27
+ exit(1)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Try to load various storage backends provided by vines-* gems and register
34
+ # them with the storage system for the config file to use.
35
+ #
36
+ # Returns nothing.
37
+ def register_storage
38
+ %w[couchdb mongodb redis sql].each do |backend|
39
+ begin
40
+ require 'vines/storage/%s' % backend
41
+ rescue LoadError
42
+ # do nothing
43
+ end
44
+ end
45
+ end
46
+
47
+ # Parse the command line arguments and run the matching sub-command
48
+ # (e.g. init, start, stop, etc).
49
+ #
50
+ # args - The ARGV array provided by the command line.
51
+ #
52
+ # Returns nothing.
53
+ def parse(args)
54
+ options = {}
55
+ parser = OptionParser.new do |opts|
56
+ opts.banner = "Usage: vines [options] #{COMMANDS.join('|')}"
57
+
58
+ opts.separator ""
59
+ opts.separator "Daemon options:"
60
+
61
+ opts.on('-d', '--daemonize', 'Run daemonized in the background') do |daemonize|
62
+ options[:daemonize] = daemonize
63
+ end
64
+
65
+ options[:log] = 'log/vines.log'
66
+ opts.on('-l', '--log FILE', 'File to redirect output (default: log/vines.log)') do |log|
67
+ options[:log] = log
68
+ end
69
+
70
+ options[:pid] = 'pid/vines.pid'
71
+ opts.on('-P', '--pid FILE', 'File to store PID (default: pid/vines.pid)') do |pid|
72
+ options[:pid] = pid
73
+ end
74
+
75
+ opts.separator ""
76
+ opts.separator "Common options:"
77
+
78
+ opts.on('-h', '--help', 'Show this message') do |help|
79
+ options[:help] = help
80
+ end
81
+
82
+ opts.on('-v', '--version', 'Show version') do |version|
83
+ options[:version] = version
84
+ end
85
+ end
86
+
87
+ begin
88
+ parser.parse!(args)
89
+ rescue
90
+ puts parser
91
+ exit(1)
92
+ end
93
+
94
+ if options[:version]
95
+ puts Vines::VERSION
96
+ exit
97
+ end
98
+
99
+ if options[:help]
100
+ puts parser
101
+ exit
102
+ end
103
+
104
+ command = args.shift
105
+ unless COMMANDS.include?(command)
106
+ puts parser
107
+ exit(1)
108
+ end
109
+
110
+ options.tap do |opts|
111
+ opts[:args] = args
112
+ opts[:command] = command
113
+ opts[:config] = File.expand_path('conf/config.rb')
114
+ opts[:pid] = File.expand_path(opts[:pid])
115
+ opts[:log] = File.expand_path(opts[:log])
116
+ end
117
+ end
118
+
119
+ # Many commands must be run in the context of a vines server directory
120
+ # created with `vines init`. If the command can't find the server's config
121
+ # file, print an error message and exit.
122
+ #
123
+ # Returns nothing.
124
+ def check_config(opts)
125
+ return if %w[bcrypt init].include?(opts[:command])
126
+ unless File.exists?(opts[:config])
127
+ puts "No config file found at #{opts[:config]}"
128
+ exit(1)
129
+ end
130
+ end
131
+ end
132
+ end
@@ -12,11 +12,18 @@ module Vines
12
12
  @stream = stream
13
13
  end
14
14
 
15
- # Authenticate s2s streams, comparing their domain to their SSL certificate.
16
- # Return +true+ if the base64 encoded domain matches the TLS certificate
17
- # presented earlier in stream negotiation. Raise a +SaslError+ if
18
- # authentication failed.
19
- # http://xmpp.org/extensions/xep-0178.html#s2s
15
+ # Authenticate server-to-server streams, comparing their domain to their
16
+ # SSL certificate.
17
+ #
18
+ # http://xmpp.org/extensions/xep-0178.html#s2s
19
+ #
20
+ # encoded - The Base64 encoded remote domain name String sent by the
21
+ # server stream.
22
+ #
23
+ # Returns true if the Base64 encoded domain matches the TLS certificate
24
+ # presented earlier in stream negotiation.
25
+ #
26
+ # Raises a SaslError if authentication failed.
20
27
  def external_auth(encoded)
21
28
  unless encoded == EMPTY
22
29
  authzid = decode64(encoded)
@@ -27,8 +34,12 @@ module Vines
27
34
  matches_from or raise SaslErrors::NotAuthorized
28
35
  end
29
36
 
30
- # Authenticate c2s streams using a username and password. Return the
31
- # authenticated +User+ or raise a +SaslError+ if authentication failed.
37
+ # Authenticate client-to-server streams using a username and password.
38
+ #
39
+ # encoded - The Base64 encoded jid and password String sent by the
40
+ # client stream.
41
+ #
42
+ # Returns the authenticated User or raises SaslError if authentication failed.
32
43
  def plain_auth(encoded)
33
44
  jid, password = decode_credentials(encoded)
34
45
  user = authenticate(jid, password)
@@ -39,7 +50,13 @@ module Vines
39
50
 
40
51
  # Storage backends should not raise errors, but if an unexpected error
41
52
  # occurs during authentication, convert it to a temporary-auth-failure.
42
- # Return the authenticated +User+ or +nil+ if authentication failed.
53
+ #
54
+ # jid - The user's jid String.
55
+ # password - The String password.
56
+ #
57
+ # Returns the authenticated User or nil if authentication failed.
58
+ #
59
+ # Raises TemoraryAuthFailure if the storage system failed.
43
60
  def authenticate(jid, password)
44
61
  log.info("Authenticating user: %s" % jid)
45
62
  @stream.storage.authenticate(jid, password).tap do |user|
@@ -50,10 +67,15 @@ module Vines
50
67
  raise SaslErrors::TemporaryAuthFailure
51
68
  end
52
69
 
53
- # Return the +JID+ and password decoded from the base64 encoded SASL PLAIN
70
+ # Return the JID and password decoded from the Base64 encoded SASL PLAIN
54
71
  # credentials formatted as authzid\0authcid\0password.
55
- # http://tools.ietf.org/html/rfc6120#section-6.3.8
56
- # http://tools.ietf.org/html/rfc4616
72
+ #
73
+ # http://tools.ietf.org/html/rfc6120#section-6.3.8
74
+ # http://tools.ietf.org/html/rfc4616
75
+ #
76
+ # encoded - The Base64 encoded String from which to extract jid and password.
77
+ #
78
+ # Returns an Array of jid String and password String.
57
79
  def decode_credentials(encoded)
58
80
  authzid, node, password = decode64(encoded).split("\x00")
59
81
  raise SaslErrors::NotAuthorized if node.nil? || node.empty? || password.nil? || password.empty?
@@ -71,7 +93,13 @@ module Vines
71
93
  # widely supported. However, Strophe and Blather send a bare JID, in
72
94
  # compliance with RFC 6120, but Smack sends just the user name as the
73
95
  # authzid. So, take care to handle non-compliant clients here.
74
- # http://tools.ietf.org/html/rfc6120#section-6.3.8
96
+ #
97
+ # http://tools.ietf.org/html/rfc6120#section-6.3.8
98
+ #
99
+ # authzid - The authzid String (may be nil).
100
+ # jid - The username String.
101
+ #
102
+ # Returns nothing.
75
103
  def validate_authzid!(authzid, jid)
76
104
  return if authzid.nil? || authzid.empty?
77
105
  authzid.downcase!
@@ -80,10 +108,18 @@ module Vines
80
108
  raise SaslErrors::InvalidAuthzid unless compliant || smack
81
109
  end
82
110
 
83
- # Decode the base64 encoded string, raising an error for invalid data.
84
- # http://tools.ietf.org/html/rfc6120#section-13.9.1
111
+ # Decode the Base64 encoded string, raising an error for invalid data.
112
+ #
113
+ # http://tools.ietf.org/html/rfc6120#section-13.9.1
114
+ #
115
+ # encoded - The Base64 encoded String.
116
+ #
117
+ # Returns a UTF-8 String.
85
118
  def decode64(encoded)
86
- Base64.strict_decode64(encoded)
119
+ Base64.strict_decode64(encoded).tap do |decoded|
120
+ decoded.force_encoding(Encoding::UTF_8)
121
+ raise SaslErrors::IncorrectEncoding unless decoded.valid_encoding?
122
+ end
87
123
  rescue
88
124
  raise SaslErrors::IncorrectEncoding
89
125
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Vines
4
- VERSION = '0.4.7'
4
+ VERSION = '0.4.8'
5
5
  end
@@ -97,6 +97,18 @@ describe Vines::Stream::SASL do
97
97
  storage.verify
98
98
  end
99
99
 
100
+ it 'passes with valid password and unicode jid' do
101
+ user = Vines::User.new(jid: 'piñata@verona.lit')
102
+ storage.expect :authenticate, user, [user.jid, 'secr3t']
103
+ stream.expect :storage, storage
104
+
105
+ encoded = Base64.strict_encode64("\x00piñata\x00secr3t")
106
+ subject.plain_auth(encoded).must_equal user
107
+
108
+ stream.verify
109
+ storage.verify
110
+ end
111
+
100
112
  it 'passes with valid password and authzid provided by strophe and blather' do
101
113
  storage.expect :authenticate, romeo, [romeo.jid, 'secr3t']
102
114
  stream.expect :storage, storage
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vines
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7
5
- prerelease:
4
+ version: 0.4.8
6
5
  platform: ruby
7
6
  authors:
8
7
  - David Graham
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-23 00:00:00.000000000 Z
11
+ date: 2013-10-30 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bcrypt-ruby
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: em-hiredis
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: eventmachine
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: http_parser.rb
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: net-ldap
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
@@ -94,7 +83,6 @@ dependencies:
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: nokogiri
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
87
  - - ~>
100
88
  - !ruby/object:Gem::Version
@@ -102,7 +90,6 @@ dependencies:
102
90
  type: :runtime
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
94
  - - ~>
108
95
  - !ruby/object:Gem::Version
@@ -110,7 +97,6 @@ dependencies:
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: minitest
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
101
  - - ~>
116
102
  - !ruby/object:Gem::Version
@@ -118,7 +104,6 @@ dependencies:
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
108
  - - ~>
124
109
  - !ruby/object:Gem::Version
@@ -126,7 +111,6 @@ dependencies:
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: rake
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
115
  - - ~>
132
116
  - !ruby/object:Gem::Version
@@ -134,7 +118,6 @@ dependencies:
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
122
  - - ~>
140
123
  - !ruby/object:Gem::Version
@@ -154,6 +137,7 @@ files:
154
137
  - README.md
155
138
  - vines.gemspec
156
139
  - bin/vines
140
+ - lib/vines/cli.rb
157
141
  - lib/vines/cluster/connection.rb
158
142
  - lib/vines/cluster/publisher.rb
159
143
  - lib/vines/cluster/pubsub.rb
@@ -324,30 +308,26 @@ files:
324
308
  homepage: http://www.getvines.org
325
309
  licenses:
326
310
  - MIT
311
+ metadata: {}
327
312
  post_install_message:
328
313
  rdoc_options: []
329
314
  require_paths:
330
315
  - lib
331
316
  required_ruby_version: !ruby/object:Gem::Requirement
332
- none: false
333
317
  requirements:
334
- - - ! '>='
318
+ - - '>='
335
319
  - !ruby/object:Gem::Version
336
320
  version: 1.9.3
337
321
  required_rubygems_version: !ruby/object:Gem::Requirement
338
- none: false
339
322
  requirements:
340
- - - ! '>='
323
+ - - '>='
341
324
  - !ruby/object:Gem::Version
342
325
  version: '0'
343
- segments:
344
- - 0
345
- hash: -1025629835892307549
346
326
  requirements: []
347
327
  rubyforge_project:
348
- rubygems_version: 1.8.23
328
+ rubygems_version: 2.0.3
349
329
  signing_key:
350
- specification_version: 3
330
+ specification_version: 4
351
331
  summary: Vines is an XMPP chat server that's easy to install and run.
352
332
  test_files:
353
333
  - test/cluster/publisher_test.rb