PageRenderTime 29ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/rails/actionpack/test/controller/request_forgery_protection_test.rb

https://bitbucket.org/javierbuilder/uncontabilidad
Ruby | 327 lines | 249 code | 54 blank | 24 comment | 0 complexity | 9b9a286a9729f703ff22e847f6279b6f MD5 | raw file
  1. require 'abstract_unit'
  2. require 'digest/sha1'
  3. ActionController::Routing::Routes.draw do |map|
  4. map.connect ':controller/:action/:id'
  5. end
  6. # simulates cookie session store
  7. class FakeSessionDbMan
  8. def self.generate_digest(data)
  9. Digest::SHA1.hexdigest("secure")
  10. end
  11. end
  12. # common controller actions
  13. module RequestForgeryProtectionActions
  14. def index
  15. render :inline => "<%= form_tag('/') {} %>"
  16. end
  17. def show_button
  18. render :inline => "<%= button_to('New', '/') {} %>"
  19. end
  20. def remote_form
  21. render :inline => "<% form_remote_tag(:url => '/') {} %>"
  22. end
  23. def unsafe
  24. render :text => 'pwn'
  25. end
  26. def rescue_action(e) raise e end
  27. end
  28. # sample controllers
  29. class RequestForgeryProtectionController < ActionController::Base
  30. include RequestForgeryProtectionActions
  31. protect_from_forgery :only => :index, :secret => 'abc'
  32. end
  33. class RequestForgeryProtectionWithoutSecretController < ActionController::Base
  34. include RequestForgeryProtectionActions
  35. protect_from_forgery
  36. end
  37. # no token is given, assume the cookie store is used
  38. class CsrfCookieMonsterController < ActionController::Base
  39. include RequestForgeryProtectionActions
  40. protect_from_forgery :only => :index
  41. end
  42. # sessions are turned off
  43. class SessionOffController < ActionController::Base
  44. protect_from_forgery :secret => 'foobar'
  45. session :off
  46. def rescue_action(e) raise e end
  47. include RequestForgeryProtectionActions
  48. end
  49. class FreeCookieController < CsrfCookieMonsterController
  50. self.allow_forgery_protection = false
  51. def index
  52. render :inline => "<%= form_tag('/') {} %>"
  53. end
  54. def show_button
  55. render :inline => "<%= button_to('New', '/') {} %>"
  56. end
  57. end
  58. # common test methods
  59. module RequestForgeryProtectionTests
  60. def teardown
  61. ActionController::Base.request_forgery_protection_token = nil
  62. end
  63. def test_should_render_form_with_token_tag
  64. get :index
  65. assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
  66. end
  67. def test_should_render_button_to_with_token_tag
  68. get :show_button
  69. assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
  70. end
  71. def test_should_render_remote_form_with_only_one_token_parameter
  72. get :remote_form
  73. assert_equal 1, @response.body.scan(@token).size
  74. end
  75. def test_should_allow_get
  76. get :index
  77. assert_response :success
  78. end
  79. def test_should_allow_post_without_token_on_unsafe_action
  80. post :unsafe
  81. assert_response :success
  82. end
  83. def test_should_not_allow_html_post_without_token
  84. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  85. assert_raises(ActionController::InvalidAuthenticityToken) { post :index, :format => :html }
  86. end
  87. def test_should_not_allow_html_put_without_token
  88. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  89. assert_raises(ActionController::InvalidAuthenticityToken) { put :index, :format => :html }
  90. end
  91. def test_should_not_allow_html_delete_without_token
  92. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  93. assert_raises(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html }
  94. end
  95. def test_should_allow_api_formatted_post_without_token
  96. assert_nothing_raised do
  97. post :index, :format => 'xml'
  98. end
  99. end
  100. def test_should_not_allow_api_formatted_put_without_token
  101. assert_nothing_raised do
  102. put :index, :format => 'xml'
  103. end
  104. end
  105. def test_should_allow_api_formatted_delete_without_token
  106. assert_nothing_raised do
  107. delete :index, :format => 'xml'
  108. end
  109. end
  110. def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
  111. assert_raises(ActionController::InvalidAuthenticityToken) do
  112. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  113. post :index, :format => 'xml'
  114. end
  115. end
  116. def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
  117. assert_raises(ActionController::InvalidAuthenticityToken) do
  118. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  119. put :index, :format => 'xml'
  120. end
  121. end
  122. def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
  123. assert_raises(ActionController::InvalidAuthenticityToken) do
  124. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  125. delete :index, :format => 'xml'
  126. end
  127. end
  128. def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
  129. assert_raises(ActionController::InvalidAuthenticityToken) do
  130. @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
  131. post :index, :format => 'xml'
  132. end
  133. end
  134. def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
  135. assert_raises(ActionController::InvalidAuthenticityToken) do
  136. @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
  137. put :index, :format => 'xml'
  138. end
  139. end
  140. def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
  141. assert_raises(ActionController::InvalidAuthenticityToken) do
  142. @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
  143. delete :index, :format => 'xml'
  144. end
  145. end
  146. def test_should_allow_xhr_post_without_token
  147. assert_nothing_raised { xhr :post, :index }
  148. end
  149. def test_should_not_allow_xhr_post_with_html_without_token
  150. @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
  151. assert_raise(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
  152. end
  153. def test_should_allow_xhr_put_without_token
  154. assert_nothing_raised { xhr :put, :index }
  155. end
  156. def test_should_allow_xhr_delete_without_token
  157. assert_nothing_raised { xhr :delete, :index }
  158. end
  159. def test_should_allow_post_with_token
  160. post :index, :authenticity_token => @token
  161. assert_response :success
  162. end
  163. def test_should_allow_put_with_token
  164. put :index, :authenticity_token => @token
  165. assert_response :success
  166. end
  167. def test_should_allow_delete_with_token
  168. delete :index, :authenticity_token => @token
  169. assert_response :success
  170. end
  171. def test_should_allow_post_with_xml
  172. @request.env['CONTENT_TYPE'] = Mime::XML.to_s
  173. post :index, :format => 'xml'
  174. assert_response :success
  175. end
  176. def test_should_allow_put_with_xml
  177. @request.env['CONTENT_TYPE'] = Mime::XML.to_s
  178. put :index, :format => 'xml'
  179. assert_response :success
  180. end
  181. def test_should_allow_delete_with_xml
  182. @request.env['CONTENT_TYPE'] = Mime::XML.to_s
  183. delete :index, :format => 'xml'
  184. assert_response :success
  185. end
  186. end
  187. # OK let's get our test on
  188. class RequestForgeryProtectionControllerTest < Test::Unit::TestCase
  189. include RequestForgeryProtectionTests
  190. def setup
  191. @controller = RequestForgeryProtectionController.new
  192. @request = ActionController::TestRequest.new
  193. @request.format = :html
  194. @response = ActionController::TestResponse.new
  195. class << @request.session
  196. def session_id() '123' end
  197. end
  198. @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
  199. ActionController::Base.request_forgery_protection_token = :authenticity_token
  200. end
  201. end
  202. class RequestForgeryProtectionWithoutSecretControllerTest < Test::Unit::TestCase
  203. def setup
  204. @controller = RequestForgeryProtectionWithoutSecretController.new
  205. @request = ActionController::TestRequest.new
  206. @response = ActionController::TestResponse.new
  207. class << @request.session
  208. def session_id() '123' end
  209. end
  210. @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
  211. ActionController::Base.request_forgery_protection_token = :authenticity_token
  212. end
  213. # def test_should_raise_error_without_secret
  214. # assert_raises ActionController::InvalidAuthenticityToken do
  215. # get :index
  216. # end
  217. # end
  218. end
  219. class CsrfCookieMonsterControllerTest < Test::Unit::TestCase
  220. include RequestForgeryProtectionTests
  221. def setup
  222. @controller = CsrfCookieMonsterController.new
  223. @request = ActionController::TestRequest.new
  224. @response = ActionController::TestResponse.new
  225. class << @request.session
  226. attr_accessor :dbman
  227. end
  228. # simulate a cookie session store
  229. @request.session.dbman = FakeSessionDbMan
  230. @token = Digest::SHA1.hexdigest("secure")
  231. ActionController::Base.request_forgery_protection_token = :authenticity_token
  232. end
  233. end
  234. class FreeCookieControllerTest < Test::Unit::TestCase
  235. def setup
  236. @controller = FreeCookieController.new
  237. @request = ActionController::TestRequest.new
  238. @response = ActionController::TestResponse.new
  239. @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
  240. end
  241. def test_should_not_render_form_with_token_tag
  242. get :index
  243. assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
  244. end
  245. def test_should_not_render_button_to_with_token_tag
  246. get :show_button
  247. assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
  248. end
  249. def test_should_allow_all_methods_without_token
  250. [:post, :put, :delete].each do |method|
  251. assert_nothing_raised { send(method, :index)}
  252. end
  253. end
  254. end
  255. class SessionOffControllerTest < Test::Unit::TestCase
  256. def setup
  257. @controller = SessionOffController.new
  258. @request = ActionController::TestRequest.new
  259. @response = ActionController::TestResponse.new
  260. @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
  261. end
  262. # TODO: Rewrite this test.
  263. # This test was passing but for the wrong reason.
  264. # Sessions aren't really being turned off, so an exception was raised
  265. # because sessions weren't on - not because the token didn't match.
  266. #
  267. # def test_should_raise_correct_exception
  268. # @request.session = {} # session(:off) doesn't appear to work with controller tests
  269. # assert_raises(ActionController::InvalidAuthenticityToken) do
  270. # post :index, :authenticity_token => @token, :format => :html
  271. # end
  272. # end
  273. end