File: pylons.decorators.secure.html

package info (click to toggle)
pylons 1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,700 kB
  • sloc: python: 3,991; makefile: 38
file content (136 lines) | stat: -rw-r--r-- 12,387 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<html>
<head>
<title>pylons.decorators.secure</title>
</head>
<body>
pylons.decorators.secure
<style>
.coverage pre {float: left; margin: 0px 1em; border: none;
               padding: 0px; }
.num pre { margin: 0px }
.nocov, .nocov pre {background-color: #faa}
.cov, .cov pre {background-color: #cfc}
div.coverage div { clear: both; height: 1.1em}
</style>
<div class="stats">
Covered: 80 lines<br/>
Missed: 0 lines<br/>
Skipped 31 lines<br/>
Percent: 100 %<br/>

</div>
<div class="coverage">
<div class="cov"><span class="num"><pre>  1</pre></span><pre>&quot;&quot;&quot;Security related decorators&quot;&quot;&quot;</pre></div>
<div class="cov"><span class="num"><pre>  2</pre></span><pre>import logging</pre></div>
<div class="cov"><span class="num"><pre>  3</pre></span><pre>import urlparse</pre></div>
<div class="skip"><span class="num"><pre>  4</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>  5</pre></span><pre>from decorator import decorator</pre></div>
<div class="cov"><span class="num"><pre>  6</pre></span><pre>try:</pre></div>
<div class="cov"><span class="num"><pre>  7</pre></span><pre>    import webhelpers.html.secure_form as secure_form</pre></div>
<div class="cov"><span class="num"><pre>  8</pre></span><pre>except ImportError:</pre></div>
<div class="cov"><span class="num"><pre>  9</pre></span><pre>    import webhelpers.pylonslib.secure_form as secure_form</pre></div>
<div class="skip"><span class="num"><pre> 10</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 11</pre></span><pre>from pylons.controllers.util import abort, redirect</pre></div>
<div class="cov"><span class="num"><pre> 12</pre></span><pre>from pylons.decorators.util import get_pylons</pre></div>
<div class="skip"><span class="num"><pre> 13</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 14</pre></span><pre>__all__ = ['authenticate_form', 'https']</pre></div>
<div class="skip"><span class="num"><pre> 15</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 16</pre></span><pre>log = logging.getLogger(__name__)</pre></div>
<div class="skip"><span class="num"><pre> 17</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 18</pre></span><pre>csrf_detected_message = (</pre></div>
<div class="cov"><span class="num"><pre> 19</pre></span><pre>    &quot;Cross-site request forgery detected, request denied. See &quot;</pre></div>
<div class="cov"><span class="num"><pre> 20</pre></span><pre>    &quot;http://en.wikipedia.org/wiki/Cross-site_request_forgery for more &quot;</pre></div>
<div class="cov"><span class="num"><pre> 21</pre></span><pre>    &quot;information.&quot;)</pre></div>
<div class="skip"><span class="num"><pre> 22</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 23</pre></span><pre>def authenticated_form(params):</pre></div>
<div class="cov"><span class="num"><pre> 24</pre></span><pre>    submitted_token = params.get(secure_form.token_key)</pre></div>
<div class="cov"><span class="num"><pre> 25</pre></span><pre>    return submitted_token is not None and \</pre></div>
<div class="cov"><span class="num"><pre> 26</pre></span><pre>        submitted_token == secure_form.authentication_token()</pre></div>
<div class="skip"><span class="num"><pre> 27</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 28</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 29</pre></span><pre>@decorator</pre></div>
<div class="cov"><span class="num"><pre> 30</pre></span><pre>def authenticate_form(func, *args, **kwargs):</pre></div>
<div class="cov"><span class="num"><pre> 31</pre></span><pre>    &quot;&quot;&quot;Decorator for authenticating a form</pre></div>
<div class="skip"><span class="num"><pre> 32</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 33</pre></span><pre>    This decorator uses an authorization token stored in the client's</pre></div>
<div class="cov"><span class="num"><pre> 34</pre></span><pre>    session for prevention of certain Cross-site request forgery (CSRF)</pre></div>
<div class="cov"><span class="num"><pre> 35</pre></span><pre>    attacks (See</pre></div>
<div class="cov"><span class="num"><pre> 36</pre></span><pre>    http://en.wikipedia.org/wiki/Cross-site_request_forgery for more</pre></div>
<div class="cov"><span class="num"><pre> 37</pre></span><pre>    information).</pre></div>
<div class="skip"><span class="num"><pre> 38</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 39</pre></span><pre>    For use with the ``webhelpers.html.secure_form`` helper functions.</pre></div>
<div class="skip"><span class="num"><pre> 40</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 41</pre></span><pre>    &quot;&quot;&quot;</pre></div>
<div class="cov"><span class="num"><pre> 42</pre></span><pre>    request = get_pylons(args).request</pre></div>
<div class="cov"><span class="num"><pre> 43</pre></span><pre>    if authenticated_form(request.POST):</pre></div>
<div class="cov"><span class="num"><pre> 44</pre></span><pre>        del request.POST[secure_form.token_key]</pre></div>
<div class="cov"><span class="num"><pre> 45</pre></span><pre>        return func(*args, **kwargs)</pre></div>
<div class="cov"><span class="num"><pre> 46</pre></span><pre>    else:</pre></div>
<div class="cov"><span class="num"><pre> 47</pre></span><pre>        log.warn('Cross-site request forgery detected, request denied: %r '</pre></div>
<div class="cov"><span class="num"><pre> 48</pre></span><pre>                 'REMOTE_ADDR: %s' % (request, request.remote_addr))</pre></div>
<div class="cov"><span class="num"><pre> 49</pre></span><pre>        abort(403, detail=csrf_detected_message)</pre></div>
<div class="skip"><span class="num"><pre> 50</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 51</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 52</pre></span><pre>def https(url_or_callable=None):</pre></div>
<div class="cov"><span class="num"><pre> 53</pre></span><pre>    &quot;&quot;&quot;Decorator to redirect to the SSL version of a page if not</pre></div>
<div class="cov"><span class="num"><pre> 54</pre></span><pre>    currently using HTTPS. Apply this decorator to controller methods</pre></div>
<div class="cov"><span class="num"><pre> 55</pre></span><pre>    (actions).</pre></div>
<div class="skip"><span class="num"><pre> 56</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 57</pre></span><pre>    Takes a url argument: either a string url, or a callable returning a</pre></div>
<div class="cov"><span class="num"><pre> 58</pre></span><pre>    string url. The callable will be called with no arguments when the</pre></div>
<div class="cov"><span class="num"><pre> 59</pre></span><pre>    decorated method is called. The url's scheme will be rewritten to</pre></div>
<div class="cov"><span class="num"><pre> 60</pre></span><pre>    https if necessary.</pre></div>
<div class="skip"><span class="num"><pre> 61</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 62</pre></span><pre>    Non-HTTPS POST requests are aborted (405 response code) by this</pre></div>
<div class="cov"><span class="num"><pre> 63</pre></span><pre>    decorator.</pre></div>
<div class="skip"><span class="num"><pre> 64</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 65</pre></span><pre>    Example:</pre></div>
<div class="skip"><span class="num"><pre> 66</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 67</pre></span><pre>    .. code-block:: python</pre></div>
<div class="skip"><span class="num"><pre> 68</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 69</pre></span><pre>        # redirect to HTTPS /pylons</pre></div>
<div class="cov"><span class="num"><pre> 70</pre></span><pre>        @https('/pylons')</pre></div>
<div class="cov"><span class="num"><pre> 71</pre></span><pre>        def index(self):</pre></div>
<div class="cov"><span class="num"><pre> 72</pre></span><pre>            do_secure()</pre></div>
<div class="skip"><span class="num"><pre> 73</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 74</pre></span><pre>        # redirect to HTTPS /auth/login, delaying the url() call until</pre></div>
<div class="skip"><span class="num"><pre> 75</pre></span><pre>        # later (as the url object may not be functional when the</pre></div>
<div class="skip"><span class="num"><pre> 76</pre></span><pre>        # decorator/method are defined)</pre></div>
<div class="cov"><span class="num"><pre> 77</pre></span><pre>        @https(lambda: url(controller='auth', action='login'))</pre></div>
<div class="cov"><span class="num"><pre> 78</pre></span><pre>        def login(self):</pre></div>
<div class="cov"><span class="num"><pre> 79</pre></span><pre>            do_secure()</pre></div>
<div class="skip"><span class="num"><pre> 80</pre></span><pre></pre></div>
<div class="skip"><span class="num"><pre> 81</pre></span><pre>        # redirect to HTTPS version of myself</pre></div>
<div class="cov"><span class="num"><pre> 82</pre></span><pre>        @https()</pre></div>
<div class="cov"><span class="num"><pre> 83</pre></span><pre>        def get(self):</pre></div>
<div class="cov"><span class="num"><pre> 84</pre></span><pre>            do_secure()</pre></div>
<div class="skip"><span class="num"><pre> 85</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 86</pre></span><pre>    &quot;&quot;&quot;</pre></div>
<div class="cov"><span class="num"><pre> 87</pre></span><pre>    def wrapper(func, *args, **kwargs):</pre></div>
<div class="cov"><span class="num"><pre> 88</pre></span><pre>        &quot;&quot;&quot;Decorator Wrapper function&quot;&quot;&quot;</pre></div>
<div class="cov"><span class="num"><pre> 89</pre></span><pre>        request = get_pylons(args).request</pre></div>
<div class="cov"><span class="num"><pre> 90</pre></span><pre>        if request.scheme.lower() == 'https':</pre></div>
<div class="cov"><span class="num"><pre> 91</pre></span><pre>            return func(*args, **kwargs)</pre></div>
<div class="cov"><span class="num"><pre> 92</pre></span><pre>        if request.method.upper() == 'POST':</pre></div>
<div class="skip"><span class="num"><pre> 93</pre></span><pre>            # don't allow POSTs (raises an exception)</pre></div>
<div class="cov"><span class="num"><pre> 94</pre></span><pre>            abort(405, headers=[('Allow', 'GET')])</pre></div>
<div class="skip"><span class="num"><pre> 95</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre> 96</pre></span><pre>        if url_or_callable is None:</pre></div>
<div class="cov"><span class="num"><pre> 97</pre></span><pre>            url = request.url</pre></div>
<div class="cov"><span class="num"><pre> 98</pre></span><pre>        elif callable(url_or_callable):</pre></div>
<div class="cov"><span class="num"><pre> 99</pre></span><pre>            url = url_or_callable()</pre></div>
<div class="cov"><span class="num"><pre>100</pre></span><pre>        else:</pre></div>
<div class="cov"><span class="num"><pre>101</pre></span><pre>            url = url_or_callable</pre></div>
<div class="skip"><span class="num"><pre>102</pre></span><pre>        # Ensure an https scheme, which also needs a host</pre></div>
<div class="cov"><span class="num"><pre>103</pre></span><pre>        parts = urlparse.urlparse(url)</pre></div>
<div class="cov"><span class="num"><pre>104</pre></span><pre>        url = urlparse.urlunparse(('https', parts[1] or request.host) +</pre></div>
<div class="cov"><span class="num"><pre>105</pre></span><pre>                                  parts[2:])</pre></div>
<div class="skip"><span class="num"><pre>106</pre></span><pre></pre></div>
<div class="cov"><span class="num"><pre>107</pre></span><pre>        log.debug('Redirecting non-https request: %s to: %s',</pre></div>
<div class="cov"><span class="num"><pre>108</pre></span><pre>                  request.path_info, url)</pre></div>
<div class="cov"><span class="num"><pre>109</pre></span><pre>        redirect(url)</pre></div>
<div class="cov"><span class="num"><pre>110</pre></span><pre>    return decorator(wrapper)</pre></div>
<div class="skip"><span class="num"><pre>111</pre></span><pre></pre></div>
</div>
</body>
</html>