sparoid 1.0.16 → 1.0.18

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11677eb6c66244eed7b68e11a2d543db02020701b990a3fdec1c6e230df7f883
4
- data.tar.gz: 3a3c8c05b72ae568bf7edb0ff95e37fa60cb9173380283e626f07455d24e9064
3
+ metadata.gz: 9d3f9a0d1d95953662422a99f8d0170ce0db8df6ec82042e7f7d6d32e1721853
4
+ data.tar.gz: b2f702533aa2d6e1a96aed917a8cc77f8aa8916395944174c74644379392d7b8
5
5
  SHA512:
6
- metadata.gz: bc14a72d7d060bad1b0bb813987a66c9464e89cb8e8dcd58cff28a91130560d91e3a5d5c49182be4465f0a8d3499f7d87e564a78b1abcf2576c4aa0bc3610550
7
- data.tar.gz: b9dffb39f58ae71e43a54aa1417c0a1f69e25f398c6354497243b01a2f5604c26023624dffc33c3b55b7f8065c29789ef34f252298feb3f883d44ac5cc58f19a
6
+ metadata.gz: c1803bdedaca58f7e172516864f502693e2478e43b7d9d5b8a0b5f306bb6284d4d19066e23235e9825c5f87ba0567f71388f19df52148cbce2637a17b8afd6d3
7
+ data.tar.gz: beb7813a740aa8d52d2689ee26c65872a45f991a9c2d2b937a46ba9451926471a064ca6635056441609a7bc8dfade4ef97aed2de130615b23d269e4ef308469e
@@ -4,15 +4,15 @@ on: [push,pull_request]
4
4
 
5
5
  jobs:
6
6
  build:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ ruby: [ 2.7, '3.0', 3.1, ruby-head ]
7
11
  runs-on: ubuntu-latest
8
12
  steps:
9
- - uses: actions/checkout@v2
10
- - name: Set up Ruby
11
- uses: ruby/setup-ruby@v1
13
+ - uses: actions/checkout@v3
14
+ - uses: ruby/setup-ruby@v1
12
15
  with:
13
- ruby-version: 2.7.2
14
- - name: Run the default task
15
- run: |
16
- gem install bundler -v 2.2.14
17
- bundle install
18
- bundle exec rake
16
+ ruby-version: ${{ matrix.ruby }}
17
+ - run: bundle install
18
+ - run: bundle exec rake
data/.rubocop.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.5
3
3
  NewCops: enable
4
+ SuggestExtensions: false
4
5
 
5
6
  Style/StringLiterals:
6
7
  Enabled: true
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [1.0.18] - 2022-10-10
2
+
3
+ - Only resolv the IP(s) once
4
+ - TCP connect to IPs in parallel
5
+ - Fix bug where 3 UDP packets was sent to each IP
6
+
7
+ ## [1.0.17] - 2021-11-15
8
+
9
+ - Raise more specific error when failing to resolv hostname
10
+
1
11
  ## [1.0.16] - 2021-08-23
2
12
 
3
13
  - Resolv host IPs before generating message (in case resolving takes a lot of time)
data/lib/sparoid/cli.rb CHANGED
@@ -6,6 +6,8 @@ require_relative "../sparoid"
6
6
  module Sparoid
7
7
  # CLI
8
8
  class CLI < Thor
9
+ map "-v" => :version
10
+
9
11
  desc "auth HOST [PORT]", "Send a authorization packet"
10
12
  method_option :config, desc: "Path to a config file, INI format, with key and hmac-key", default: "~/.sparoid.ini"
11
13
  def auth(host, port = 8484)
@@ -19,12 +21,8 @@ module Sparoid
19
21
  desc "connect HOST PORT [SPA-PORT]", "Send a SPA, TCP connect, and then pass the FD back to the parent"
20
22
  method_option :config, desc: "Path to a config file, INI format, with key and hmac-key", default: "~/.sparoid.ini"
21
23
  def connect(host, port, spa_port = 8484)
22
- begin
23
- send_auth(host, spa_port, options[:config])
24
- rescue Errno::ENOENT
25
- warn "Sparoid: Config not found"
26
- end
27
- Sparoid.fdpass(host, port)
24
+ ips = send_auth(host, spa_port, options[:config])
25
+ Sparoid.fdpass(ips, port)
28
26
  rescue StandardError => e
29
27
  abort "Sparoid: #{e.message} (#{host})"
30
28
  end
@@ -34,6 +32,11 @@ module Sparoid
34
32
  Sparoid.keygen
35
33
  end
36
34
 
35
+ desc "version", "Show version and exit"
36
+ def version
37
+ puts "#{Sparoid::VERSION} (ruby)"
38
+ end
39
+
37
40
  def self.exit_on_failure?
38
41
  true
39
42
  end
@@ -49,8 +52,8 @@ module Sparoid
49
52
  File.readlines(File.expand_path(path)).map! { |line| line.split("=", 2).map!(&:strip) }.to_h
50
53
  rescue Errno::ENOENT
51
54
  {
52
- "key" => ENV["SPAROID_KEY"],
53
- "hmac-key" => ENV["SPAROID_HMAC_KEY"]
55
+ "key" => ENV.fetch("SPAROID_KEY", nil),
56
+ "hmac-key" => ENV.fetch("SPAROID_HMAC_KEY", nil)
54
57
  }
55
58
  end
56
59
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sparoid
4
- VERSION = "1.0.16"
4
+ VERSION = "1.0.18"
5
5
  end
data/lib/sparoid.rb CHANGED
@@ -13,17 +13,19 @@ module Sparoid
13
13
 
14
14
  # Send an authorization packet
15
15
  def auth(key, hmac_key, host, port)
16
- ips = Resolv.getaddresses(host)
17
- raise(Error, "Sparoid failed to resolv #{host}") if ips.empty?
16
+ addrs = Addrinfo.getaddrinfo(host, port, :INET, :DGRAM)
17
+ raise(ResolvError, "Sparoid failed to resolv #{host}") if addrs.empty?
18
18
 
19
19
  msg = message(cached_public_ip)
20
20
  data = prefix_hmac(hmac_key, encrypt(key, msg))
21
- sendmsg(ips, port, data)
21
+ sendmsg(addrs, data)
22
22
 
23
23
  # wait some time for the server to actually open the port
24
24
  # if we don't wait the next SYN package will be dropped
25
25
  # and it have to be redelivered, adding 1 second delay
26
26
  sleep 0.02
27
+
28
+ addrs.map(&:ip_address) # return resolved IP(s)
27
29
  end
28
30
 
29
31
  # Generate new aes and hmac keys, print to stdout
@@ -36,23 +38,42 @@ module Sparoid
36
38
  end
37
39
 
38
40
  # Connect to a TCP server and pass the FD to the parent
39
- def fdpass(host, port, connect_timeout: 20)
40
- tcp = Socket.tcp host, port, connect_timeout: connect_timeout
41
- parent = Socket.for_fd(1)
42
- parent.sendmsg "\0", 0, nil, Socket::AncillaryData.unix_rights(tcp)
41
+ def fdpass(ips, port, connect_timeout: 10)
42
+ # try connect to all IPs
43
+ sockets = ips.map do |ip|
44
+ Socket.new(Socket::AF_INET, Socket::SOCK_STREAM).tap do |s|
45
+ s.connect_nonblock(Socket.sockaddr_in(port, ip), exception: false)
46
+ end
47
+ end
48
+ # wait for any socket to be connected
49
+ until sockets.empty?
50
+ _, writeable, = IO.select(nil, sockets, nil, connect_timeout)
51
+ writeable.each do |s|
52
+ idx = sockets.index(s)
53
+ sockets.delete_at(idx) # don't retry this socket again
54
+ ip = ips.delete_at(idx) # find the IP for the socket
55
+ s.connect_nonblock(Socket.sockaddr_in(port, ip)) # check for errors
56
+ # pass the connected FD to the parent process over STDOUT
57
+ Socket.for_fd(1).sendmsg "\0", 0, nil, Socket::AncillaryData.unix_rights(s)
58
+ exit 0 # exit as fast as possible so that other sockets don't connect
59
+ rescue SystemCallError
60
+ next # ignore connection errors, hopefully at least one succeeds
61
+ end
62
+ end
63
+ exit 1 # all connections failed
43
64
  end
44
65
 
45
66
  private
46
67
 
47
- def sendmsg(ips, port, data)
48
- UDPSocket.open do |socket|
49
- ips.each do |ip|
50
- socket.connect ip, port
51
- socket.sendmsg data, 0
52
- rescue StandardError => e
53
- warn "Sparoid error: #{e.message}"
54
- end
68
+ def sendmsg(addrs, data)
69
+ socket = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM
70
+ addrs.each do |addr|
71
+ socket.sendmsg data, 0, addr
72
+ rescue StandardError => e
73
+ warn "Sparoid error: #{e.message}"
55
74
  end
75
+ ensure
76
+ socket.close
56
77
  end
57
78
 
58
79
  def encrypt(key, data)
@@ -131,6 +152,8 @@ module Sparoid
131
152
 
132
153
  class Error < StandardError; end
133
154
 
155
+ class ResolvError < Error; end
156
+
134
157
  # Instance of SPAroid that only resolved public_ip once
135
158
  class Instance
136
159
  include Sparoid
data/sparoid.gemspec CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ["lib"]
28
28
 
29
29
  spec.add_dependency "thor"
30
+ spec.metadata["rubygems_mfa_required"] = "true"
30
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.16
4
+ version: 1.0.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Hörberg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-23 00:00:00.000000000 Z
11
+ date: 2022-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -54,6 +54,7 @@ metadata:
54
54
  homepage_uri: https://github.com/84codes/sparoid.rb
55
55
  source_code_uri: https://github.com/84codes/sparoid.rb
56
56
  changelog_uri: https://raw.githubusercontent.com/84codes/sparoid.rb/main/CHANGELOG.md
57
+ rubygems_mfa_required: 'true'
57
58
  post_install_message:
58
59
  rdoc_options: []
59
60
  require_paths:
@@ -69,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
70
  - !ruby/object:Gem::Version
70
71
  version: '0'
71
72
  requirements: []
72
- rubygems_version: 3.2.15
73
+ rubygems_version: 3.3.7
73
74
  signing_key:
74
75
  specification_version: 4
75
76
  summary: Single Packet Authorisation client