Class: Rodsec::Transaction

Inherits:
Object
  • Object
show all
Includes:
StringPointers
Defined in:
lib/rodsec/transaction.rb

Constant Summary

Constants included from StringPointers

StringPointers::EMPTY_STRING

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from StringPointers

#strptr

Constructor Details

#initialize(msc, ruleset, txn_log_tag: nil) ⇒ Transaction

txn_log_tag must be convertible to a string. Defaults to self.object_id.to_s it shows up in as the first argument passed to Modsec’s log_blk.

Raises:



8
9
10
11
12
13
14
15
16
# File 'lib/rodsec/transaction.rb', line 8

def initialize msc, ruleset, txn_log_tag: nil
  raise Error, "msc must be a #{Modsec}" unless Modsec === msc
  raise Error, "ruleset must be a #{RuleSet}" unless RuleSet === ruleset

  @msc, @ruleset = msc, ruleset
  @txn_log_tag = Fiddle::Pointer[(txn_log_tag || object_id).to_s]
  @txn_ptr = Wrapper.msc_new_transaction msc.msc_ptr, ruleset.rules_ptr, @txn_log_tag
  @txn_ptr.free = Wrapper['msc_transaction_cleanup']
end

Instance Attribute Details

#mscObject (readonly)

Returns the value of attribute msc.



20
21
22
# File 'lib/rodsec/transaction.rb', line 20

def msc
  @msc
end

#rulesetObject (readonly)

Returns the value of attribute ruleset.



20
21
22
# File 'lib/rodsec/transaction.rb', line 20

def ruleset
  @ruleset
end

#txn_ptrObject (readonly)

Returns the value of attribute txn_ptr.



18
19
20
# File 'lib/rodsec/transaction.rb', line 18

def txn_ptr
  @txn_ptr
end

Instance Method Details

#connection!(client_host, client_port, server_host, server_port) ⇒ Object

Phase CONNECTION / SecRules 0 check for intervention afterwards



39
40
41
42
43
44
45
46
47
48
# File 'lib/rodsec/transaction.rb', line 39

def connection! client_host, client_port, server_host, server_port
  rv = Wrapper.msc_process_connection \
    txn_ptr,
    (strptr client_host), (Integer client_port),
    (strptr server_host), (Integer server_port)

  rv == 1 or raise Error, "msc_process_connection failed for #{[client_host, client_port, server_host, server_port].inspect}"

  intervention!
end

#loggingObject

Phase LOGGING. SecRules 5. just logs all information. Response can be sent prior to this, or concurrently.



177
178
179
180
181
182
# File 'lib/rodsec/transaction.rb', line 177

def logging
  rv = Wrapper.msc_process_logging txn_ptr
  rv == 1 or raise 'msc_process_logging failed'

  self
end

#request_body!(body) ⇒ Object

Phase REQUEST_BODY. SecRules 2

body can be a String, or an Enumerable of strings



103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/rodsec/transaction.rb', line 103

def request_body! body
  enum_of_body(body).each do |body_part|
    body_part = body_part.to_s
    rv = Wrapper.msc_append_request_body txn_ptr, (strptr body_part), body_part.bytesize
    rv == 1 or raise Error, "msc_append_request_body failed for #{truncate_inspect body_part}"
  end

  # This MUST be called, otherwise rules aren't triggered.
  rv = Wrapper.msc_process_request_body txn_ptr
  rv == 1 or raise Error, "msc_process_request_body failed"

  intervention!
end

#request_headers!(header_hash) ⇒ Object

Phase REQUEST_HEADERS. SecRules 1



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rodsec/transaction.rb', line 64

def request_headers! header_hash
  errors = header_hash.each_with_object [] do |(key, val), errors|
    key = key.to_s; val = val.to_s
    rv = Wrapper.msc_add_n_request_header txn_ptr, (strptr key), key.bytesize, (strptr val), val.bytesize
    rv == 1 or errors << "msc_add_n_request_header failed adding #{[key,val].inspect}"
  end

  raise Error errors if errors.any?

  rv = Wrapper.msc_process_request_headers txn_ptr
  rv == 1 or raise "msc_process_request_headers failed"

  intervention!
end

#response_body!(body) ⇒ Object

Phase RESPONSE_BODY. SecRules 4

body can be a String, or an Enumerable of strings



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rodsec/transaction.rb', line 147

def response_body! body
  enum_of_body(body).each do |body_part|
    body_part = body_part.to_s

    # This return value works differently to all the other msc_ calls.
    #  0 means
    #    body too large, so it was only partially processed;
    #    or
    #    body too large and and intervention is needed.
    #
    #  1 means everything went fine
    #
    # so we ignore the non-useful return code and rely on intervention! below
    Wrapper.msc_append_response_body txn_ptr, (strptr body_part), body_part.bytesize
  end

  # This MUST be called, otherwise rules aren't triggered
  rv = Wrapper.msc_process_response_body txn_ptr
  rv == 1 or raise Error, 'msc_process_response_body failed'

  intervention!
end

#response_headers!(http_status_code = 200, http_with_version = 'HTTP 1.1', header_hash) ⇒ Object

Phase RESPONSE_HEADERS. SecRules 3 http_status_code is one of the 200, 401, 404 etc codes http_with_version seems to be things like ‘HTTP 1.2’, not entirely sure.

Raises:



124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/rodsec/transaction.rb', line 124

def response_headers! http_status_code = 200, http_with_version = 'HTTP 1.1', header_hash
  errors = header_hash.each_with_object [] do |(key, val), errors|
    key = key.to_s; val = val.to_s
    rv = Wrapper.msc_add_n_response_header txn_ptr, (strptr key), key.bytesize, (strptr val), val.bytesize
    rv == 1 or errors << "msc_add_n_response_header failed adding #{[key,val].inspect}"
  end

  raise Error, errors if errors.any?

  rv = Wrapper.msc_process_response_headers txn_ptr, (Integer http_status_code), (strptr http_with_version)
  rv == 1 or raise "msc_process_response_headers failed"

  intervention!
end

#uri!(uri, verb, http_version) ⇒ Object

Phase URI / 1.5 check for intervention afterwards verb is GET POST etc http_version is ‘1.1’, ‘1.2’ etc



55
56
57
58
59
60
# File 'lib/rodsec/transaction.rb', line 55

def uri! uri, verb, http_version
  rv = Wrapper.msc_process_uri txn_ptr, (strptr uri), (strptr verb), (strptr http_version)
  rv == 1 or raise Error "msc_process_uri failed for #{[uri, verb, http_version].inspect}"

  intervention!
end