summaryrefslogtreecommitdiffstats
path: root/debian/vendor-h2o/share/h2o/mruby
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 21:12:02 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 21:12:02 +0000
commit77e50caaf2ef81cd91075cf836fed0e75718ffb4 (patch)
tree53b7b411290b63192fc9e924a3b6b65cdf67e9d0 /debian/vendor-h2o/share/h2o/mruby
parentAdding upstream version 1.8.3. (diff)
downloaddnsdist-77e50caaf2ef81cd91075cf836fed0e75718ffb4.tar.xz
dnsdist-77e50caaf2ef81cd91075cf836fed0e75718ffb4.zip
Adding debian version 1.8.3-2.debian/1.8.3-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/vendor-h2o/share/h2o/mruby')
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/acl.rb130
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/bootstrap.rb31
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/dos_detector.rb134
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/htpasswd.rb129
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/lru_cache.rb81
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/preloads.rb3
-rw-r--r--debian/vendor-h2o/share/h2o/mruby/trie_addr.rb73
7 files changed, 581 insertions, 0 deletions
diff --git a/debian/vendor-h2o/share/h2o/mruby/acl.rb b/debian/vendor-h2o/share/h2o/mruby/acl.rb
new file mode 100644
index 0000000..7a7ba53
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/acl.rb
@@ -0,0 +1,130 @@
+# Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+require File.expand_path(File.dirname(__FILE__)) + "/bootstrap.rb"
+
+module H2O
+
+ module ACL
+
+ def acl(&block)
+ context = H2O::ConfigurationContext.instance
+ if context.get_value(:acl_handler) then
+ raise "acl can be called only once for each handler configuration"
+ end
+ acl_handler = ACLHandler.new(&block)
+ context.set_value(:acl_handler, acl_handler)
+ context.add_post_handler_generation_hook(proc {|handler|
+ if handler != acl_handler
+ raise "acl configuration is ignored"
+ end
+ })
+ return acl_handler
+ end
+
+ class ACLHandler
+
+ class ConditionalHandler
+ def initialize(handler, cond)
+ @handler = handler
+ @cond = cond
+ end
+
+ def satisfy?(env)
+ return @cond.nil? || MatchingBlock.new(env).instance_eval(&@cond)
+ end
+
+ def call(env)
+ return @handler.call(env) if satisfy?(env)
+ return [399, {}, []]
+ end
+ end
+
+ def initialize(&block)
+ @acl = []
+ instance_eval(&block)
+ end
+
+ def call(env)
+ @acl.each {|ac|
+ return ac.call(env) if ac.satisfy?(env)
+ }
+ return [399, {}, []]
+ end
+
+ def use(handler, &cond)
+ ch = ConditionalHandler.new(handler, cond)
+ @acl << ch
+ end
+
+ def respond(status, header={}, body=[], &cond)
+ use(proc {|env| [status, header, body] }, &cond)
+ end
+
+ def deny(&cond)
+ respond(403, {}, ["Forbidden"], &cond)
+ end
+
+ def allow(&cond)
+ respond(399, {}, [], &cond)
+ end
+
+ def redirect(location, status=302, &cond)
+ respond(status, { "Location" => location }, [], &cond)
+ end
+
+ class MatchingBlock
+ def initialize(env)
+ @env = env
+ end
+
+ def addr(forwarded=true)
+ addr = @env['REMOTE_ADDR']
+ if forwarded && (xff = @env['HTTP_X_FORWARDED_FOR'])
+ xaddr = xff.split(",")[0]
+ addr = xaddr if xaddr
+ end
+ return addr || ""
+ end
+
+ def path
+ return @env["PATH_INFO"] || ""
+ end
+
+ def method
+ return @env["REQUEST_METHOD"] || ""
+ end
+
+ def header(name)
+ name = 'HTTP_' + name.gsub(/-/, '_').upcase;
+ return @env[name] || ""
+ end
+
+ def user_agent
+ return header("User-Agent") || ""
+ end
+
+ end
+
+ end
+
+ end
+
+end
diff --git a/debian/vendor-h2o/share/h2o/mruby/bootstrap.rb b/debian/vendor-h2o/share/h2o/mruby/bootstrap.rb
new file mode 100644
index 0000000..df8cbb9
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/bootstrap.rb
@@ -0,0 +1,31 @@
+module H2O
+
+ class ConfigurationContext
+ def self.instance()
+ @@instance
+ end
+ def self.reset()
+ @@instance = self.new()
+ end
+ def initialize()
+ @values = {}
+ @post_handler_generation_hooks = []
+ end
+ def get_value(key)
+ @values[key]
+ end
+ def set_value(key, value)
+ @values[key] = value
+ end
+ def delete_value(key)
+ @values[key].delete
+ end
+ def add_post_handler_generation_hook(hook)
+ @post_handler_generation_hooks << hook
+ end
+ def call_post_handler_generation_hooks(handler)
+ @post_handler_generation_hooks.each {|hook| hook.call(handler) }
+ end
+ end
+
+end
diff --git a/debian/vendor-h2o/share/h2o/mruby/dos_detector.rb b/debian/vendor-h2o/share/h2o/mruby/dos_detector.rb
new file mode 100644
index 0000000..15de2bc
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/dos_detector.rb
@@ -0,0 +1,134 @@
+# Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+require File.expand_path(File.dirname(__FILE__)) + "/lru_cache.rb"
+
+class DoSDetector
+
+ def initialize(config={})
+ config = {
+ :strategy => CountingStrategy.new,
+ :callback => self.class.default_callback,
+ :forwarded => true,
+ :cache_size => 128,
+ }.merge(config)
+
+ @strategy = config[:strategy]
+ @callback = config[:callback]
+ @forwarded = !!(config[:forwarded])
+ @cache = LRUCache.new(config[:cache_size])
+ raise "strategy must not be nil" if @strategy.nil?
+ raise "callback must not be nil" if @callback.nil?
+ end
+
+ def self.default_callback
+ Proc.new do |env, detected, ip|
+ if detected
+ [ 403, { "Content-Type" => "text/plain" }, [ "Forbidden" ] ]
+ else
+ [ 399, {}, [] ]
+ end
+ end
+ end
+
+ def self.fallthrough_callback
+ Proc.new do |env, detected, ip, vars|
+ if detected
+ vars ||= {}
+ env_headers = vars.merge({:ip => ip}).map { |k, v| [ "x-fallthru-set-dos-#{k}", v.to_s ] }.to_h
+ [ 399, env_headers, [] ]
+ else
+ [ 399, {}, [] ]
+ end
+ end
+ end
+
+ def call(env)
+ now = Time.now.to_i
+
+ ip = env['REMOTE_ADDR']
+ if @forwarded && (xff = env['HTTP_X_FORWARDED_FOR'])
+ ip = xff.split(",")[0]
+ end
+
+ unless client = @cache.get(ip)
+ client = { :ip => ip }
+ @cache.set(ip, client)
+ end
+
+ detected, *args = @strategy.detect?(client, now, env)
+ return @callback.call(env, detected, ip, *args)
+ end
+
+ class CountingStrategy
+
+ def initialize(config={})
+ config = {
+ :period => 10,
+ :threshold => 100,
+ :ban_period => 300,
+ }.merge(config)
+ @period = config[:period]
+ @threshold = config[:threshold]
+ @ban_period = config[:ban_period]
+ raise "period must be greater than zero" if @period <= 0
+ raise "threshold must be greater than zero" if @threshold <= 0
+ raise "ban_period must not be negative" if @ban_period < 0
+ end
+
+ def detect?(client, now, env)
+ count = countup(client, now)
+
+ banned_until = client[:banned_until] || 0
+ if banned_until >= now
+ detected = true
+ else
+ detected = count >= @threshold
+ if detected
+ banned_until = now + @ban_period
+ client[:banned_until] = banned_until
+ end
+ end
+
+ return detected, { :count => count, :banned_until => banned_until }
+ end
+
+ private
+
+ def countup(client, now)
+ count = client[:count] || 0
+ period_index = client[:period_index] || 0
+
+ current_period_index = (now / @period).floor
+ if current_period_index > period_index
+ count -= (current_period_index - period_index) * @threshold
+ count = 0 if count < 0
+ client[:period_index] = current_period_index
+ end
+
+ count += 1
+ client[:count] = count
+
+ return count
+ end
+
+ end
+
+end
diff --git a/debian/vendor-h2o/share/h2o/mruby/htpasswd.rb b/debian/vendor-h2o/share/h2o/mruby/htpasswd.rb
new file mode 100644
index 0000000..d8f65fe
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/htpasswd.rb
@@ -0,0 +1,129 @@
+# based on public-domain code by cho45
+#
+# Copyright (c) 2015 DeNA Co., Ltd., Kazuho Oku
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+class Htpasswd
+
+ attr_accessor :path
+ attr_accessor :realm
+
+ def initialize(path, realm)
+ @path = path
+ @realm = realm
+ end
+
+ def call(env)
+ if /\/\.ht/.match(env['PATH_INFO'])
+ return [ 404, { "Content-Type" => "text/plain" }, [ "not found" ] ]
+ end
+ auth = env['HTTP_AUTHORIZATION']
+ if auth
+ method, cred = *auth.split(' ')
+ if method.casecmp("basic") == 0
+ user, pass = cred.unpack("m")[0].split(':', 2)
+ begin
+ if lookup(user, pass)
+ return [ 399, { "x-fallthru-set-remote-user" => user }, [] ]
+ end
+ rescue => e
+ $stderr.puts "failed to validate password using file:#{@path}:#{e.message}"
+ return [ 500, { "Content-Type" => "text/plain" }, [ "Internal Server Error" ] ]
+ end
+ end
+ end
+ return [ 401, { "Content-Type" => "text/plain", "WWW-Authenticate" => "Basic realm=\"#{@realm}\"" }, [ "Authorization Required" ] ]
+ end
+
+ def lookup(user, pass)
+ File.open(@path) do |file|
+ file.each_line do |line|
+ line_user, hash = line.chomp.split(':', 2)
+ if user == line_user && self.class.validate(pass, hash)
+ return true
+ end
+ end
+ end
+ return false
+ end
+
+ def Htpasswd.crypt_md5(pass, salt)
+ ctx = Digest::MD5.new.update("#{pass}$apr1$#{salt}")
+ final = Digest::MD5.new.update("#{pass}#{salt}#{pass}").digest!.bytes
+
+ l = pass.length
+ while l > 0
+ ctx.update(final[0 .. (l > 16 ? 16 : l) - 1].pack("C*"))
+ l -= 16
+ end
+
+ l = pass.length
+ while l > 0
+ ctx.update(l % 2 != 0 ? "\0" : pass[0])
+ l >>= 1
+ end
+
+ final = ctx.digest!
+
+ 1000.times do |i|
+ ctx = Digest::MD5.new
+ ctx.update(i % 2 != 0 ? pass : final)
+ ctx.update(salt) if i % 3 != 0
+ ctx.update(pass) if i % 7 != 0
+ ctx.update(i % 2 != 0 ? final : pass)
+ final = ctx.digest!
+ end
+
+ final = final.bytes
+ hash = ""
+ for a, b, c in [[0, 6, 12], [1, 7, 13], [2, 8, 14], [3, 9, 15], [4, 10, 5]]
+ hash << _to64(final[a] << 16 | final[b] << 8 | final[c], 4)
+ end
+ hash << _to64(final[11], 2)
+
+ "$apr1$#{salt}$#{hash}"
+ end
+
+ def Htpasswd._to64(v, n)
+ chars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ output = ""
+ n.times do
+ output << chars[v & 0x3f]
+ v >>= 6
+ end
+ output
+ end
+
+ def Htpasswd.crypt_sha1(pass)
+ "{SHA}" + [Digest::SHA1.new.update(pass).digest!].pack("m").chomp
+ end
+
+ def Htpasswd.validate(pass, hash)
+ if /^\$apr1\$(.*)\$/.match(hash)
+ encoded = crypt_md5(pass, $1)
+ elsif /^{SHA}/.match(hash)
+ encoded = crypt_sha1(pass)
+ else
+ raise "crypt-style password hash is not supported"
+ end
+ return encoded == hash
+ end
+
+end
diff --git a/debian/vendor-h2o/share/h2o/mruby/lru_cache.rb b/debian/vendor-h2o/share/h2o/mruby/lru_cache.rb
new file mode 100644
index 0000000..e92b838
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/lru_cache.rb
@@ -0,0 +1,81 @@
+# Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+class LRUCache
+
+ def initialize(capacity)
+ @capacity = capacity
+ @head = nil
+ @tail = nil
+ @nodes = {}
+ raise "capacity must not be negative" if @capacity < 0
+ end
+
+ def set(key, value)
+ if ! @head
+ @nodes[key] = @head = @tail = [ nil, nil, key, value ]
+ elsif node = @nodes[key]
+ move_to_head(node)
+ node[3] = value
+ else
+ node = [ nil, @head, key, value ]
+ @head[0] = node
+ @nodes[key] = @head = node
+ end
+
+ while @nodes.size > @capacity do
+ @nodes.delete(@tail[2])
+ @tail = @tail[0]
+ if @tail
+ @tail[1] = nil
+ else
+ @head = nil
+ break
+ end
+ end
+
+ return value
+ end
+
+ def get(key)
+ node = @nodes[key]
+ return nil unless node
+ move_to_head(node)
+ return node[3]
+ end
+
+ private
+
+ def move_to_head(node)
+ if node == @head
+ return
+ elsif node == @tail
+ @tail = @tail[0]
+ @tail[1] = nil
+ end
+ node[0][1] = node[1]
+ node[1][0] = node[0] if node[1]
+ node[0] = nil
+ node[1] = @head
+ @head[0] = node
+ @head = node
+ end
+
+end
diff --git a/debian/vendor-h2o/share/h2o/mruby/preloads.rb b/debian/vendor-h2o/share/h2o/mruby/preloads.rb
new file mode 100644
index 0000000..5a62d58
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/preloads.rb
@@ -0,0 +1,3 @@
+require File.expand_path(File.dirname(__FILE__)) + "/bootstrap.rb"
+require File.expand_path(File.dirname(__FILE__)) + "/acl.rb"
+include H2O::ACL
diff --git a/debian/vendor-h2o/share/h2o/mruby/trie_addr.rb b/debian/vendor-h2o/share/h2o/mruby/trie_addr.rb
new file mode 100644
index 0000000..727f2c7
--- /dev/null
+++ b/debian/vendor-h2o/share/h2o/mruby/trie_addr.rb
@@ -0,0 +1,73 @@
+# Copyright (c) 2016 DeNA Co., Ltd., Ichito Nagata
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+class TrieAddr
+ def self.generate_leaf(default=nil)
+ leaf = Hash.new
+ leaf.default = default || leaf
+ (0..255).each {|i| leaf[i.to_s] = leaf }
+ return leaf
+ end
+ REJECT = self.generate_leaf
+ FULFILL = self.generate_leaf(REJECT)
+
+ def initialize
+ @root = Hash.new(REJECT)
+ end
+
+ def add(cidr)
+ if cidr.kind_of?(Array)
+ cidr.each {|c| add(c) }
+ return self
+ end
+
+ ip, length = cidr.split('/', 2)
+ s = ip.split(".", 4).map {|o| o.to_i}
+ if s.length != 4
+ raise ArgumentError, "invalid IPv4 address: #{ip}"
+ end
+ length = (length || 32).to_i
+
+ netmask = ~((1 << (32 - length)) - 1) & 0xffffffff
+ nip = (s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3]
+ nip &= netmask
+
+ cur = @root
+ while length > 8 do
+ octet = ((nip >> 24) & 0xff).to_s
+ return self if cur[octet].equal?(FULFILL)
+ if !cur[octet] || cur[octet].equal?(REJECT)
+ cur[octet] = Hash.new(REJECT)
+ end
+ cur = cur[octet]
+ nip <<= 8
+ length -= 8
+ end
+ lower = (nip >> 24) & 0xff
+ upper = lower + (1 << (8 - length)) - 1;
+ (lower..upper).each {|t| cur[t.to_s] = FULFILL }
+ return self
+ end
+
+ def match?(ip)
+ s = ip.split(".", 4)
+ @root[s[0]][s[1]][s[2]][s[3]].equal?(FULFILL)
+ end
+end