linzer 0.6.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c09a63a7eae654921b40e0462b463b3e70867522fcedaf42f03373dd72ef55a5
4
- data.tar.gz: b5fea79104954db4289fbf7e4df9f8e589827943cb62eb2836bd0b970611263a
3
+ metadata.gz: d2ec6a2a846f2bb066bdd658c2e50a869ceff52f65f3e5f8670cc5509af6069c
4
+ data.tar.gz: 5401df5ea61c39290b61a21cf19c4eaddc537abe908067a47688c1f209c982e3
5
5
  SHA512:
6
- metadata.gz: 89572382dde42b597eeafecceca1572222cff5d20bba50345b0e3849f47d510cdbcfbc0988295e16b783aa9d28235a95e56b49302a53577e744dc8575253a419
7
- data.tar.gz: bc8c2850994c211b4549dcd07d64ddb14fd54d948a05153d8011042eb4cd2b4adca4d8f80ab983a8c8c71deefc2473994fa479ec8b7ec00063dfa86ead7be7a4
6
+ metadata.gz: 53c504c5c0f886d3e73332d7d8bf7072137519a218ca6a005824f8ad073fb589dd91f2e7980aa02b232c17dd80a87923141e57b094087fb4f412dddbf5588a9f
7
+ data.tar.gz: 0a99fc9611e6b26ae820fecfe09e10a6c610be20bdf8f9c3fd7c6fab031f82f6f7fa109359470a2a65b7d7cd9817c21259e59fe6f99e50a1c6326d965b0df944
data/.standard.yml CHANGED
@@ -7,3 +7,4 @@ ignore:
7
7
  - Layout/ExtraSpacing
8
8
  - Layout/HashAlignment
9
9
  - Layout/ArgumentAlignment
10
+ - Style/EmptyCaseCondition
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.1] - 2024-12-02
4
+
5
+ - Add more validation checks on HTTP field component identifiers and parameters.
6
+
7
+ - Relax rack version requirements.
8
+
9
+ - Update uri dependency to the latest version.
10
+
3
11
  ## [0.6.0] - 2024-04-06
4
12
 
5
13
  - Support parameters on HTTP field component identifiers.
data/lib/linzer/common.rb CHANGED
@@ -18,10 +18,29 @@ module Linzer
18
18
  if components.include?("@signature-params")
19
19
  raise Error.new "Invalid component in signature input"
20
20
  end
21
+
21
22
  msg = "Cannot verify signature. Missing component in message: %s"
22
- components.each { |c| raise Error.new msg % "\"#{c}\"" unless message.field?(c) }
23
+ components.each do |c|
24
+ raise Error.new msg % "\"#{c}\"" unless message.field?(c)
25
+ end
26
+
27
+ validate_uniqueness components
28
+ end
29
+
30
+ def validate_uniqueness(components)
23
31
  msg = "Invalid signature. Duplicated component in signature input."
24
- raise Error.new msg if components.size != components.uniq.size
32
+
33
+ uniq_components =
34
+ components
35
+ .partition { |c| c.start_with?("@") }
36
+ .flat_map
37
+ .with_index do |group, idx|
38
+ group
39
+ .map { |comp| Starry.parse_item(idx.zero? ? comp[1..] : comp) }
40
+ .uniq { |comp| [comp.value, comp.parameters] }
41
+ end
42
+
43
+ raise Error.new msg if components.count != uniq_components.count
25
44
  end
26
45
  end
27
46
  end
@@ -47,7 +47,6 @@ module Linzer
47
47
  return nil if name.nil?
48
48
 
49
49
  if field_name.start_with?("@")
50
- return nil if name.parameters["tr"]
51
50
  retrieve(name, :derived)
52
51
  else
53
52
  retrieve(name, :field)
@@ -79,13 +78,48 @@ module Linzer
79
78
  nil
80
79
  end
81
80
 
81
+ def validate_parameters(name, method)
82
+ has_unknown = name.parameters.any? { |p, _| !KNOWN_PARAMETERS.include?(p) }
83
+ return nil if has_unknown
84
+
85
+ has_name = name.parameters["name"]
86
+ has_req = name.parameters["req"]
87
+ has_sf = name.parameters["sf"] || name.parameters.key?("key")
88
+ has_bs = name.parameters["bs"]
89
+ value = name.value
90
+
91
+ # Section 2.2.8 of RFC 9421
92
+ return nil if has_name && value != :"query-param"
93
+
94
+ # No derived values come from trailers section
95
+ return nil if method == :derived && name.parameters["tr"]
96
+
97
+ # From: 2.1. HTTP Fields:
98
+ # The bs parameter, which requires the raw bytes of the field values
99
+ # from the message, is not compatible with the use of the sf or key
100
+ # parameters, which require the parsed data structures of the field
101
+ # values after combination
102
+ return nil if has_sf && has_bs
103
+
104
+ # req param only makes sense on responses with an associated request
105
+ return nil if has_req && (!response? || !attached_request?)
106
+
107
+ name
108
+ end
109
+
110
+ KNOWN_PARAMETERS = %w[sf key bs req tr name]
111
+ private_constant :KNOWN_PARAMETERS
112
+
82
113
  def retrieve(name, method)
114
+ if !name.parameters.empty?
115
+ valid_params = validate_parameters(name, method)
116
+ return nil if !valid_params
117
+ end
118
+
83
119
  has_req = name.parameters["req"]
84
120
  has_sf = name.parameters["sf"] || name.parameters.key?("key")
85
121
  has_bs = name.parameters["bs"]
86
122
 
87
- return nil if has_req && (!response? || !attached_request?)
88
-
89
123
  if has_req
90
124
  name.parameters.delete("req")
91
125
  return req(name, method)
@@ -93,10 +127,13 @@ module Linzer
93
127
 
94
128
  value = send(method, name)
95
129
 
96
- key = name.parameters["key"]
97
- value = sf(value, key) if has_sf
98
- value = bs(value) if has_bs
99
- value
130
+ case
131
+ when has_sf
132
+ key = name.parameters["key"]
133
+ sf(value, key)
134
+ when has_bs then bs(value)
135
+ else value
136
+ end
100
137
  end
101
138
 
102
139
  def derived(name)
@@ -128,7 +165,8 @@ module Linzer
128
165
  def derive(operation, method)
129
166
  return nil unless operation.respond_to?(method)
130
167
  value = operation.public_send(method)
131
- return "?" + value if method == :query_string
168
+ return "?" + value if method == :query_string
169
+ return value.downcase if %i[authority scheme].include?(method)
132
170
  value
133
171
  end
134
172
 
@@ -144,10 +182,12 @@ module Linzer
144
182
  def sf(value, key = nil)
145
183
  dict = Starry.parse_dictionary(value)
146
184
 
147
- obj = dict[key] if key
148
- return Starry.serialize(obj.is_a?(Starry::InnerList) ? [obj] : obj) if key
149
-
150
- Starry.serialize(dict)
185
+ if key
186
+ obj = dict[key]
187
+ Starry.serialize(obj.is_a?(Starry::InnerList) ? [obj] : obj)
188
+ else
189
+ Starry.serialize(dict)
190
+ end
151
191
  end
152
192
 
153
193
  def bs(value)
@@ -11,7 +11,8 @@ module Linzer
11
11
  request_method = Rack.const_get(verb.upcase)
12
12
  args = {
13
13
  "REQUEST_METHOD" => request_method,
14
- "PATH_INFO" => uri.to_str
14
+ "PATH_INFO" => uri.to_str,
15
+ "rack.input" => StringIO.new
15
16
  }
16
17
 
17
18
  Rack::Request.new(build_rack_env(headers).merge(args))
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Linzer
4
- VERSION = "0.6.0"
5
-
6
- def self.ruby_dev?
7
- RUBY_ENGINE == "ruby" && RUBY_PATCHLEVEL == -1 && /\Aruby 3.[0-9].0dev/ =~ RUBY_DESCRIPTION
8
- end
4
+ VERSION = "0.6.1"
9
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linzer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Landaeta
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-06 00:00:00.000000000 Z
11
+ date: 2024-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: openssl
@@ -56,48 +56,54 @@ dependencies:
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: '0.1'
59
+ version: '0.2'
60
60
  type: :runtime
61
61
  prerelease: false
62
62
  version_requirements: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
- version: '0.1'
66
+ version: '0.2'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: rack
69
69
  requirement: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - "~>"
71
+ - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: '3.0'
73
+ version: '2.2'
74
+ - - "<"
75
+ - !ruby/object:Gem::Version
76
+ version: '4.0'
74
77
  type: :runtime
75
78
  prerelease: false
76
79
  version_requirements: !ruby/object:Gem::Requirement
77
80
  requirements:
78
- - - "~>"
81
+ - - ">="
79
82
  - !ruby/object:Gem::Version
80
- version: '3.0'
83
+ version: '2.2'
84
+ - - "<"
85
+ - !ruby/object:Gem::Version
86
+ version: '4.0'
81
87
  - !ruby/object:Gem::Dependency
82
88
  name: uri
83
89
  requirement: !ruby/object:Gem::Requirement
84
90
  requirements:
85
91
  - - "~>"
86
92
  - !ruby/object:Gem::Version
87
- version: '0.12'
93
+ version: '1.0'
88
94
  - - ">="
89
95
  - !ruby/object:Gem::Version
90
- version: 0.12.0
96
+ version: 1.0.2
91
97
  type: :runtime
92
98
  prerelease: false
93
99
  version_requirements: !ruby/object:Gem::Requirement
94
100
  requirements:
95
101
  - - "~>"
96
102
  - !ruby/object:Gem::Version
97
- version: '0.12'
103
+ version: '1.0'
98
104
  - - ">="
99
105
  - !ruby/object:Gem::Version
100
- version: 0.12.0
106
+ version: 1.0.2
101
107
  description:
102
108
  email:
103
109
  - miguel@miguel.cc
@@ -127,7 +133,6 @@ files:
127
133
  - lib/linzer/signer.rb
128
134
  - lib/linzer/verifier.rb
129
135
  - lib/linzer/version.rb
130
- - linzer.gemspec
131
136
  homepage: https://github.com/nomadium/linzer
132
137
  licenses:
133
138
  - MIT
data/linzer.gemspec DELETED
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/linzer/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "linzer"
7
- spec.version = Linzer::VERSION
8
- spec.authors = ["Miguel Landaeta"]
9
- spec.email = %w[miguel@miguel.cc]
10
-
11
- spec.summary = "An implementation of HTTP Messages Signatures (RFC9421)"
12
- spec.homepage = "https://github.com/nomadium/linzer"
13
- spec.license = "MIT"
14
- spec.required_ruby_version = ">= 2.6.0"
15
-
16
- spec.metadata["homepage_uri"] = spec.homepage
17
- spec.metadata["source_code_uri"] = spec.homepage
18
- spec.metadata["changelog_uri"] = spec.homepage + "/blob/master/CHANGELOG.md"
19
-
20
- # Specify which files should be added to the gem when it is released.
21
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
- spec.files = Dir.chdir(__dir__) do
23
- `git ls-files -z`.split("\x0").reject do |f|
24
- (File.expand_path(f) == __FILE__) ||
25
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
26
- end
27
- end
28
- spec.bindir = "exe"
29
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
- spec.require_paths = ["lib"]
31
-
32
- spec.add_runtime_dependency "openssl", "~> 3.0", ">= 3.0.0"
33
- spec.add_runtime_dependency "ed25519", "~> 1.3", ">= 1.3.0"
34
- spec.add_runtime_dependency "starry", "~> 0.1" unless Linzer.ruby_dev?
35
- spec.add_runtime_dependency "rack", "~> 3.0"
36
- spec.add_runtime_dependency "uri", "~> 0.12", ">= 0.12.0"
37
- end