From 77e50caaf2ef81cd91075cf836fed0e75718ffb4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 23:12:02 +0200 Subject: Adding debian version 1.8.3-2. Signed-off-by: Daniel Baumann --- debian/vendor-h2o/share/h2o/mruby/acl.rb | 130 +++++++++++++++++++++ debian/vendor-h2o/share/h2o/mruby/bootstrap.rb | 31 +++++ debian/vendor-h2o/share/h2o/mruby/dos_detector.rb | 134 ++++++++++++++++++++++ debian/vendor-h2o/share/h2o/mruby/htpasswd.rb | 129 +++++++++++++++++++++ debian/vendor-h2o/share/h2o/mruby/lru_cache.rb | 81 +++++++++++++ debian/vendor-h2o/share/h2o/mruby/preloads.rb | 3 + debian/vendor-h2o/share/h2o/mruby/trie_addr.rb | 73 ++++++++++++ 7 files changed, 581 insertions(+) create mode 100644 debian/vendor-h2o/share/h2o/mruby/acl.rb create mode 100644 debian/vendor-h2o/share/h2o/mruby/bootstrap.rb create mode 100644 debian/vendor-h2o/share/h2o/mruby/dos_detector.rb create mode 100644 debian/vendor-h2o/share/h2o/mruby/htpasswd.rb create mode 100644 debian/vendor-h2o/share/h2o/mruby/lru_cache.rb create mode 100644 debian/vendor-h2o/share/h2o/mruby/preloads.rb create mode 100644 debian/vendor-h2o/share/h2o/mruby/trie_addr.rb (limited to 'debian/vendor-h2o/share/h2o/mruby') 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 -- cgit v1.2.3