ronin-web-server 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
data/gemspec.yml ADDED
@@ -0,0 +1,31 @@
1
+ name: ronin-web-server
2
+ summary: A custom Ruby web server based on Sinatra.
3
+ description: |
4
+ ronin-web-server is a custom Ruby web server based on Sinatra tailored for
5
+ security research and development.
6
+
7
+ license: LGPL-3.0
8
+ authors: Postmodern
9
+ email: postmodern.mod3@gmail.com
10
+ homepage: https://ronin-rb.dev/
11
+ has_yard: true
12
+
13
+ metadata:
14
+ documentation_uri: https://rubydoc.info/gems/ronin-web-server
15
+ source_code_uri: https://github.com/postmodern/ronin-web-server
16
+ bug_tracker_uri: https://github.com/postmodern/ronin-web-server/issues
17
+ changelog_uri: https://github.com/postmodern/ronin-web-server/blob/master/ChangeLog.md
18
+ rubygems_mfa_required: 'true'
19
+
20
+ required_ruby_version: ">= 3.0.0"
21
+
22
+ dependencies:
23
+ webrick: ~> 1.0
24
+ rack: ~> 2.2
25
+ rack-user_agent: ~> 0.5
26
+ sinatra: ~> 3.0
27
+ # Ronin dependencies:
28
+ ronin-support: ~> 1.0.0.beta1
29
+
30
+ development_dependencies:
31
+ bundler: ~> 2.0
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-web-server - A custom Ruby web server based on Sinatra.
4
+ #
5
+ # Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-web-server is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-web-server is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-web-server. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/web/server/base'
22
+
23
+ module Ronin
24
+ module Web
25
+ module Server
26
+ #
27
+ # The main Web Server class used by {Web.server}.
28
+ #
29
+ class App < Base
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # ronin-web-server - A custom Ruby web server based on Sinatra.
4
+ #
5
+ # Copyright (c) 2006-2022 Hal Brodigan (postmodern.mod3 at gmail.com)
6
+ #
7
+ # ronin-web-server is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # ronin-web-server is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Lesser General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with ronin-web-server. If not, see <https://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ require 'ronin/web/server/request'
22
+ require 'ronin/web/server/response'
23
+ require 'ronin/web/server/routing'
24
+ require 'ronin/web/server/helpers'
25
+ require 'ronin/web/server/conditions'
26
+
27
+ require 'rack'
28
+ require 'sinatra/base'
29
+ require 'rack/user_agent'
30
+
31
+ module Ronin
32
+ module Web
33
+ module Server
34
+ #
35
+ # The base-class for all Ronin Web Servers. Extends
36
+ # [Sinatra::Base](http://rubydoc.info/gems/sinatra/Sinatra/Base)
37
+ # with additional {Routing routing methods}, {Helpers helper methods} and
38
+ # Sinatra {Conditions conditions}.
39
+ #
40
+ # ## Routing Methods
41
+ #
42
+ # * {Routing::ClassMethods#any any}: registers a route that responds to
43
+ # `GET`, `POST`, `PUT`, `PATCH`, `DELETE` and `OPTIONS` requests.
44
+ # * {Routing::ClassMethods#default default}: registers the default route.
45
+ # * {Routing::ClassMethods#basic_auth basic_auth}: enables Basic-Auth
46
+ # authentication for the whole app.
47
+ # * {Routing::ClassMethods#redirect redirect}: adds a route that simply
48
+ # redirects to another URL.
49
+ # * {Routing::ClassMethods#file file}: mounts a file at the given path.
50
+ # a given file.
51
+ # * {Routing::ClassMethods#directory directory}: mounts a directory at
52
+ # the given path.
53
+ # * {Routing::ClassMethods#public_dir public_dir}: mounts a directory
54
+ # at the root.
55
+ # * {Routing::ClassMethods#vhost vhost}: mounts a Rack app for the given
56
+ # vhost.
57
+ # * {Routing::ClassMethods#mount mount}: mounts a Rack app at the given
58
+ # path.
59
+ #
60
+ # ## Helper Methods
61
+ #
62
+ # * {Helpers#h h}: escapes HTML entities.
63
+ # * {Helpers#file file}: sends a file.
64
+ # * {Helpers#mime_type_for mime_type_for}: returns the MIME type for the
65
+ # file.
66
+ # * {Helpers#content_type_for content_type_for}: sets the `Content-Type`
67
+ # for the file.
68
+ #
69
+ # ## Routing Conditions
70
+ #
71
+ # * {Conditions::ClassMethods#client_ip client_ip}: filters requests
72
+ # based on their client IP address.
73
+ # * {Conditions::ClassMethods#asn asn}: filters requests by the client
74
+ # IP's ASN number.
75
+ # * {Conditions::ClassMethods#country_code country_code}: filters requests
76
+ # by the client IP's ASN country code.
77
+ # * {Conditions::ClassMethods#asn_name asn_name}: filters requests by the
78
+ # client IP's ASN company/ISP name.
79
+ # * {Conditions::ClassMethods#host host}: filters requests based on the
80
+ # `Host` header.
81
+ # * {Conditions::ClassMethods#referer referer}: filters requests based on
82
+ # the `Referer` header.
83
+ # * {Conditions::ClassMethods#user_agent user_agent}: filters requests
84
+ # based on the `User-Agent` header.
85
+ # * {Conditions::ClassMethods#browser browser}: filters requests based on
86
+ # the browser name within the `User-Agent` header.
87
+ # * {Conditions::ClassMethods#browser_version browser_version}: filters
88
+ # requests based on the browser version within the `User-Agent` header.
89
+ # * {Conditions::ClassMethods#device_type device_type}: filters requests
90
+ # based on the device type within the `User-Agent` header.
91
+ # * {Conditions::ClassMethods#os os}: filters requests based on the OS
92
+ # within the `User-Agent` header.
93
+ # * {Conditions::ClassMethods#os_version os_version}: filters requests
94
+ # based on the OS version within the `User-Agent` header.
95
+ #
96
+ # ## Examples
97
+ #
98
+ # require 'ronin/web/server'
99
+ #
100
+ # class App < Ronin::Web::Server::Base
101
+ #
102
+ # # mount a file
103
+ # file '/sitemap.xml', './files/sitemap.xml'
104
+ #
105
+ # # mount a directory
106
+ # directory '/downloads/', '/tmp/downloads/'
107
+ #
108
+ # get '/' do
109
+ # # renders views/index.erb
110
+ # erb :index
111
+ # end
112
+ #
113
+ # get '/test' do
114
+ # "raw text here"
115
+ # end
116
+ #
117
+ # end
118
+ #
119
+ # App.run!
120
+ #
121
+ class Base < Sinatra::Base
122
+
123
+ include Server::Routing
124
+ include Server::Helpers
125
+ include Server::Conditions
126
+
127
+ # Default interface to run the Web Server on
128
+ DEFAULT_HOST = '0.0.0.0'
129
+
130
+ # Default port to run the Web Server on
131
+ DEFAULT_PORT = 8000
132
+
133
+ use Rack::UserAgent
134
+
135
+ set :host, DEFAULT_HOST
136
+ set :port, DEFAULT_PORT
137
+
138
+ before do
139
+ @request = Request.new(@env)
140
+ @response = Response.new
141
+ end
142
+
143
+ not_found { [404, {'Content-Type' => 'text/html'}, ['']] }
144
+
145
+ #
146
+ # Run the web server.
147
+ #
148
+ # @param [Hash] options Additional options.
149
+ #
150
+ # @option options [String] :host
151
+ # The host the server will listen on.
152
+ #
153
+ # @option options [Integer] :port
154
+ # The port the server will bind to.
155
+ #
156
+ # @option options [String] :server
157
+ # The Web Server to run on.
158
+ #
159
+ # @option options [Boolean] :background (false)
160
+ # Specifies wether the server will run in the background or run
161
+ # in the foreground.
162
+ #
163
+ # @api public
164
+ #
165
+ def self.run!(options={})
166
+ set(options)
167
+
168
+ handler = detect_rack_handler
169
+ handler_name = handler.name.gsub(/.*::/, '')
170
+
171
+ # rubocop:disable Lint/ShadowingOuterLocalVariable
172
+ runner = lambda { |handler,server|
173
+ begin
174
+ handler.run(server,Host: bind, Port: port) do |server|
175
+ trap(:INT) { quit!(server,handler_name) }
176
+ trap(:TERM) { quit!(server,handler_name) }
177
+
178
+ set :running, true
179
+ end
180
+ rescue Errno::EADDRINUSE
181
+ warn "ronin-web-server: address is already in use: #{bind}:#{port}"
182
+ end
183
+ }
184
+ # rubocop:enable Lint/ShadowingOuterLocalVariable
185
+
186
+ if options[:background]
187
+ Thread.new(handler,self,&runner)
188
+ else
189
+ runner.call(handler,self)
190
+ end
191
+
192
+ return self
193
+ end
194
+
195
+ #
196
+ # Stops the web server.
197
+ #
198
+ # @param [#call] server
199
+ # The Rack Handler server.
200
+ #
201
+ # @param [String] handler_name
202
+ # The name of the handler.
203
+ #
204
+ # @api semipublic
205
+ #
206
+ def self.quit!(server,handler_name)
207
+ # Use thins' hard #stop! if available, otherwise just #stop
208
+ server.respond_to?(:stop!) ? server.stop! : server.stop
209
+ end
210
+
211
+ end
212
+ end
213
+ end
214
+ end