sparoid 1.0.17 → 1.0.19

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: 8747bc66fcbc1b4f3e31d7246d2608298a882df7d5661aef6d51c7f7b99f406c
4
- data.tar.gz: 99e0f9044333f8d17e022f406e519abcd9977c420a86003fb4d69d891ba92475
3
+ metadata.gz: aa860bf3df506199abf0f4abb417458de5758c1f87d2c7226688ed57f8f7a089
4
+ data.tar.gz: 46d9e5756c5eaaf85cd5cd51ebcf67aadc48929cb161d11a15236b24ddf02086
5
5
  SHA512:
6
- metadata.gz: 16095424a1dce5589c2922191ce96a380dd0e973dcc77c1715ec0fe9af376b4caf3127645808c2d87a161797d7d929135fa80d32be8fd06e7ef14a86cefad72f
7
- data.tar.gz: 2a56181b6d57bc511ea35e10128f9536ad4bc480fb8fae007facd5e2ee7feb8cee3a7b4aeae910b1c03c5670b20de35f7f470e495d1b5a57dd3b5a422f0cc288
6
+ metadata.gz: 6601f26feedc978e69aee6c10b573fb7a0cf0304da6a083f7236ccfaa4b12ea0586b263845a65bcb7bde7ba217bae299f3c941eaa8592e16291851a3395b82f8
7
+ data.tar.gz: 6e71a0ee6ab5627e589808f753aed3d6dc39c6c04ada839fccbc85138d6bf46c391b7cb0565a738179d143b9e17a9cde8c37b6fbe28d525b734346690ba09434
@@ -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,9 @@
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
+
1
7
  ## [1.0.17] - 2021-11-15
2
8
 
3
9
  - Raise more specific error when failing to resolv hostname
data/lib/sparoid/cli.rb CHANGED
@@ -21,12 +21,8 @@ module Sparoid
21
21
  desc "connect HOST PORT [SPA-PORT]", "Send a SPA, TCP connect, and then pass the FD back to the parent"
22
22
  method_option :config, desc: "Path to a config file, INI format, with key and hmac-key", default: "~/.sparoid.ini"
23
23
  def connect(host, port, spa_port = 8484)
24
- begin
25
- send_auth(host, spa_port, options[:config])
26
- rescue Errno::ENOENT
27
- warn "Sparoid: Config not found"
28
- end
29
- Sparoid.fdpass(host, port)
24
+ ips = send_auth(host, spa_port, options[:config])
25
+ Sparoid.fdpass(ips, port)
30
26
  rescue StandardError => e
31
27
  abort "Sparoid: #{e.message} (#{host})"
32
28
  end
@@ -56,8 +52,8 @@ module Sparoid
56
52
  File.readlines(File.expand_path(path)).map! { |line| line.split("=", 2).map!(&:strip) }.to_h
57
53
  rescue Errno::ENOENT
58
54
  {
59
- "key" => ENV["SPAROID_KEY"],
60
- "hmac-key" => ENV["SPAROID_HMAC_KEY"]
55
+ "key" => ENV.fetch("SPAROID_KEY", nil),
56
+ "hmac-key" => ENV.fetch("SPAROID_HMAC_KEY", nil)
61
57
  }
62
58
  end
63
59
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sparoid
4
- VERSION = "1.0.17"
4
+ VERSION = "1.0.19"
5
5
  end
data/lib/sparoid.rb CHANGED
@@ -6,24 +6,26 @@ require "openssl"
6
6
  require "resolv"
7
7
 
8
8
  # Single Packet Authorisation client
9
- module Sparoid
9
+ module Sparoid # rubocop:disable Metrics/ModuleLength
10
10
  extend self
11
11
 
12
12
  SPAROID_CACHE_PATH = ENV.fetch("SPAROID_CACHE_PATH", "/tmp/.sparoid_public_ip")
13
13
 
14
14
  # Send an authorization packet
15
15
  def auth(key, hmac_key, host, port)
16
- ips = Resolv.getaddresses(host)
17
- raise(ResolvError, "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,44 @@ 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) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
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
+ break if writeable.nil? # All sockets timedout
52
+
53
+ writeable.each do |s|
54
+ idx = sockets.index(s)
55
+ sockets.delete_at(idx) # don't retry this socket again
56
+ ip = ips.delete_at(idx) # find the IP for the socket
57
+ s.connect_nonblock(Socket.sockaddr_in(port, ip)) # check for errors
58
+ # pass the connected FD to the parent process over STDOUT
59
+ Socket.for_fd(1).sendmsg "\0", 0, nil, Socket::AncillaryData.unix_rights(s)
60
+ exit 0 # exit as fast as possible so that other sockets don't connect
61
+ rescue SystemCallError
62
+ next # ignore connection errors, hopefully at least one succeeds
63
+ end
64
+ end
65
+ exit 1 # all connections failed
43
66
  end
44
67
 
45
68
  private
46
69
 
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
70
+ def sendmsg(addrs, data)
71
+ socket = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM
72
+ addrs.each do |addr|
73
+ socket.sendmsg data, 0, addr
74
+ rescue StandardError => e
75
+ warn "Sparoid error: #{e.message}"
55
76
  end
77
+ ensure
78
+ socket.close
56
79
  end
57
80
 
58
81
  def encrypt(key, data)
@@ -108,7 +131,7 @@ module Sparoid
108
131
  Resolv::IPv4.create f.read
109
132
  end
110
133
  rescue ArgumentError => e
111
- return write_cache if e.message =~ /cannot interpret as IPv4 address/
134
+ return write_cache if /cannot interpret as IPv4 address/.match?(e.message)
112
135
 
113
136
  raise e
114
137
  end
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.17
4
+ version: 1.0.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Hörberg
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-15 00:00:00.000000000 Z
11
+ date: 2022-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- description:
27
+ description:
28
28
  email:
29
29
  - carl@84codes.com
30
30
  executables:
@@ -54,7 +54,8 @@ 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
- post_install_message:
57
+ rubygems_mfa_required: 'true'
58
+ post_install_message:
58
59
  rdoc_options: []
59
60
  require_paths:
60
61
  - lib
@@ -69,8 +70,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
70
  - !ruby/object:Gem::Version
70
71
  version: '0'
71
72
  requirements: []
72
- rubygems_version: 3.1.4
73
- signing_key:
73
+ rubygems_version: 3.3.7
74
+ signing_key:
74
75
  specification_version: 4
75
76
  summary: Single Packet Authorisation client
76
77
  test_files: []