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.



161
162
163
164
165
166
# File 'lib/rodsec/transaction.rb', line 161

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



96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/rodsec/transaction.rb', line 96

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"
  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



140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rodsec/transaction.rb', line 140

def response_body! body
  enum_of_body(body).each do |body_part|
    body_part = body_part.to_s
    rv = Wrapper.msc_append_response_body txn_ptr, (strptr body_part), body_part.bytesize
    rv == 1 or raise Error, 'msc_append_response_body failed'
  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:



117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rodsec/transaction.rb', line 117

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