Fossil SCM
Improved anti-robot captcha.
Commit
206089acd1be4b95e8315d5e8063ac26c6f15b77c3035c535a594b387cf12591
Parent
54afc94ce057369…
1 file changed
+70
-19
+70
-19
| --- src/robot.c | ||
| +++ src/robot.c | ||
| @@ -22,10 +22,12 @@ | ||
| 22 | 22 | #include "config.h" |
| 23 | 23 | #include "robot.h" |
| 24 | 24 | #include <assert.h> |
| 25 | 25 | #include <time.h> |
| 26 | 26 | |
| 27 | +#define POW_COOKIE "fossil-proofofwork" | |
| 28 | + | |
| 27 | 29 | /* |
| 28 | 30 | ** Rewrite the current page with a robot squelch captcha and return 1. |
| 29 | 31 | ** |
| 30 | 32 | ** Or, if valid proof-of-work is present as either a query parameter or |
| 31 | 33 | ** as a cookie, then return 0. |
| @@ -61,14 +63,14 @@ | ||
| 61 | 63 | h2 = (h2 % 900000000) + 100000000; |
| 62 | 64 | |
| 63 | 65 | /* If there is already a proof-of-work cookie with this value |
| 64 | 66 | ** that means that the user agent has already authenticated. |
| 65 | 67 | */ |
| 66 | - z = P("fossil-proofofwork"); | |
| 68 | + z = P(POW_COOKIE); | |
| 67 | 69 | if( z |
| 68 | 70 | && (atoi(z)==h1 || atoi(z)==h2) |
| 69 | - && !cgi_is_qp("fossil-proofofwork") ){ | |
| 71 | + && !cgi_is_qp(POW_COOKIE) ){ | |
| 70 | 72 | return 0; |
| 71 | 73 | } |
| 72 | 74 | |
| 73 | 75 | /* Check for a proof query parameter. If found, that means that |
| 74 | 76 | ** the captcha has just now passed, so set the proof-of-work cookie |
| @@ -76,39 +78,45 @@ | ||
| 76 | 78 | */ |
| 77 | 79 | z = P("proof"); |
| 78 | 80 | if( z |
| 79 | 81 | && (atoi(z)==h1 || atoi(z)==h2) |
| 80 | 82 | ){ |
| 81 | - cgi_set_cookie("fossil-proofofwork",z,"/",900); | |
| 83 | + cgi_set_cookie(POW_COOKIE,z,"/",900); | |
| 82 | 84 | return 0; |
| 83 | 85 | } |
| 84 | 86 | cgi_tag_query_parameter("proof"); |
| 85 | 87 | |
| 86 | 88 | /* Ask the client to present proof-of-work */ |
| 87 | 89 | cgi_reset_content(); |
| 88 | 90 | cgi_set_content_type("text/html"); |
| 89 | - style_header("Captcha"); | |
| 90 | - @ <h1>Prove That You Are Human</h1> | |
| 91 | + style_header("Browser Verification"); | |
| 92 | + @ <h1 id="x1">Checking to see if you are a robot<span id="x2"></span></h1> | |
| 91 | 93 | @ <form method="GET"> |
| 92 | - @ <p>Press the button below</p><p> | |
| 94 | + @ <p id="x3" style="visibility:hidden;">\ | |
| 95 | + @ Press <input type="submit" id="x5" value="Ok" focus> to continue</p> | |
| 93 | 96 | cgi_query_parameters_to_hidden(); |
| 94 | - @ <input id="vx" type="hidden" name="proof" value="0"> | |
| 95 | - @ <input id="cx" type="submit" value="Wait..." disabled> | |
| 97 | + @ <input id="x4" type="hidden" name="proof" value="0"> | |
| 96 | 98 | @ </form> |
| 97 | 99 | @ <script nonce='%s(style_nonce())'> |
| 98 | - @ function Nhtot1520(x){return document.getElementById(x);} | |
| 99 | - @ function Aoxlxzajv(h){\ | |
| 100 | - @ Nhtot1520("vx").value=h;\ | |
| 101 | - @ Nhtot1520("cx").value="Ok";\ | |
| 102 | - @ Nhtot1520("cx").disabled=false;\ | |
| 103 | - @ } | |
| 104 | - @ function Vhcnyarsm(h,a){\ | |
| 105 | - @ if(a>0){setTimeout(Vhcnyarsm,1,h+a,a-1);}else{Aoxlxzajv(h);}\ | |
| 106 | - @ } | |
| 107 | - k = 200 + h2%99; | |
| 100 | + @ function aaa(x){return document.getElementById(x);} | |
| 101 | + @ function bbb(h,a){ | |
| 102 | + @ aaa("x4").value=h | |
| 103 | + @ if((a%%75)==0){ | |
| 104 | + @ aaa("x2").textContent=aaa("x2").textContent+"."; | |
| 105 | + @ } | |
| 106 | + @ if(a>0){ | |
| 107 | + @ setTimeout(bbb,1,h+a,a-1); | |
| 108 | + @ }else{ | |
| 109 | + @ aaa("x3").style.visibility="visible"; | |
| 110 | + @ aaa("x2").textContent=""; | |
| 111 | + @ aaa("x1").textContent="All clear"; | |
| 112 | + @ aaa("x5").focus(); | |
| 113 | + @ } | |
| 114 | + @ } | |
| 115 | + k = 800 + h2%99; | |
| 108 | 116 | h2 = (k*k + k)/2; |
| 109 | - @ setTimeout(function(){Vhcnyarsm(%u(h1-h2),%u(k));},10); | |
| 117 | + @ setTimeout(function(){bbb(%u(h1-h2),%u(k));},10); | |
| 110 | 118 | @ </script> |
| 111 | 119 | style_finish_page(); |
| 112 | 120 | return 1; |
| 113 | 121 | } |
| 114 | 122 | |
| @@ -162,5 +170,48 @@ | ||
| 162 | 170 | if( robot_proofofwork() ){ |
| 163 | 171 | return 1; |
| 164 | 172 | } |
| 165 | 173 | return 0; |
| 166 | 174 | } |
| 175 | + | |
| 176 | + | |
| 177 | +/* | |
| 178 | +** WEBPAGE: test-robotck | |
| 179 | +** | |
| 180 | +** Run the robot_restrict() function using the value of the "name=" | |
| 181 | +** query parameter as an argument. Used for testing the robot_restrict() | |
| 182 | +** logic. | |
| 183 | +** | |
| 184 | +** Whenever this page is successfully rendered (when it doesn't go to | |
| 185 | +** the captcha) it deletes the proof-of-work cookie. So reloading the | |
| 186 | +** page will reset the cookie and restart the verification. | |
| 187 | +*/ | |
| 188 | +void robot_restrict_test_page(void){ | |
| 189 | + const char *zName = P("name"); | |
| 190 | + const char *zP1 = P("proof"); | |
| 191 | + const char *zP2 = P(POW_COOKIE); | |
| 192 | + const char *z; | |
| 193 | + if( zName==0 || zName[0]==0 ) zName = g.zPath; | |
| 194 | + login_check_credentials(); | |
| 195 | + if( !g.perm.Admin ){ login_needed(0); return; } | |
| 196 | + g.zLogin = 0; | |
| 197 | + if( robot_restrict(zName) ) return; | |
| 198 | + style_set_current_feature("test"); | |
| 199 | + style_header("robot_restrict() test"); | |
| 200 | + @ <h1>Captcha passed</h1> | |
| 201 | + @ | |
| 202 | + @ <p> | |
| 203 | + if( zP1 && zP1[0] ){ | |
| 204 | + @ proof=%h(zP1)<br> | |
| 205 | + } | |
| 206 | + if( zP2 && zP2[0] ){ | |
| 207 | + @ fossil_proofofwork=%h(zP2)<br> | |
| 208 | + cgi_set_cookie(POW_COOKIE,"",0,-1); | |
| 209 | + } | |
| 210 | + z = db_get("robot-restrict",robot_restrict_default()); | |
| 211 | + if( z && z[0] ){ | |
| 212 | + @ robot-restrict=%h(z)</br> | |
| 213 | + } | |
| 214 | + @ </p> | |
| 215 | + @ <p><a href="%R/test-robotck/%h(zName)">Retry</a> | |
| 216 | + style_finish_page(); | |
| 217 | +} | |
| 167 | 218 |
| --- src/robot.c | |
| +++ src/robot.c | |
| @@ -22,10 +22,12 @@ | |
| 22 | #include "config.h" |
| 23 | #include "robot.h" |
| 24 | #include <assert.h> |
| 25 | #include <time.h> |
| 26 | |
| 27 | /* |
| 28 | ** Rewrite the current page with a robot squelch captcha and return 1. |
| 29 | ** |
| 30 | ** Or, if valid proof-of-work is present as either a query parameter or |
| 31 | ** as a cookie, then return 0. |
| @@ -61,14 +63,14 @@ | |
| 61 | h2 = (h2 % 900000000) + 100000000; |
| 62 | |
| 63 | /* If there is already a proof-of-work cookie with this value |
| 64 | ** that means that the user agent has already authenticated. |
| 65 | */ |
| 66 | z = P("fossil-proofofwork"); |
| 67 | if( z |
| 68 | && (atoi(z)==h1 || atoi(z)==h2) |
| 69 | && !cgi_is_qp("fossil-proofofwork") ){ |
| 70 | return 0; |
| 71 | } |
| 72 | |
| 73 | /* Check for a proof query parameter. If found, that means that |
| 74 | ** the captcha has just now passed, so set the proof-of-work cookie |
| @@ -76,39 +78,45 @@ | |
| 76 | */ |
| 77 | z = P("proof"); |
| 78 | if( z |
| 79 | && (atoi(z)==h1 || atoi(z)==h2) |
| 80 | ){ |
| 81 | cgi_set_cookie("fossil-proofofwork",z,"/",900); |
| 82 | return 0; |
| 83 | } |
| 84 | cgi_tag_query_parameter("proof"); |
| 85 | |
| 86 | /* Ask the client to present proof-of-work */ |
| 87 | cgi_reset_content(); |
| 88 | cgi_set_content_type("text/html"); |
| 89 | style_header("Captcha"); |
| 90 | @ <h1>Prove That You Are Human</h1> |
| 91 | @ <form method="GET"> |
| 92 | @ <p>Press the button below</p><p> |
| 93 | cgi_query_parameters_to_hidden(); |
| 94 | @ <input id="vx" type="hidden" name="proof" value="0"> |
| 95 | @ <input id="cx" type="submit" value="Wait..." disabled> |
| 96 | @ </form> |
| 97 | @ <script nonce='%s(style_nonce())'> |
| 98 | @ function Nhtot1520(x){return document.getElementById(x);} |
| 99 | @ function Aoxlxzajv(h){\ |
| 100 | @ Nhtot1520("vx").value=h;\ |
| 101 | @ Nhtot1520("cx").value="Ok";\ |
| 102 | @ Nhtot1520("cx").disabled=false;\ |
| 103 | @ } |
| 104 | @ function Vhcnyarsm(h,a){\ |
| 105 | @ if(a>0){setTimeout(Vhcnyarsm,1,h+a,a-1);}else{Aoxlxzajv(h);}\ |
| 106 | @ } |
| 107 | k = 200 + h2%99; |
| 108 | h2 = (k*k + k)/2; |
| 109 | @ setTimeout(function(){Vhcnyarsm(%u(h1-h2),%u(k));},10); |
| 110 | @ </script> |
| 111 | style_finish_page(); |
| 112 | return 1; |
| 113 | } |
| 114 | |
| @@ -162,5 +170,48 @@ | |
| 162 | if( robot_proofofwork() ){ |
| 163 | return 1; |
| 164 | } |
| 165 | return 0; |
| 166 | } |
| 167 |
| --- src/robot.c | |
| +++ src/robot.c | |
| @@ -22,10 +22,12 @@ | |
| 22 | #include "config.h" |
| 23 | #include "robot.h" |
| 24 | #include <assert.h> |
| 25 | #include <time.h> |
| 26 | |
| 27 | #define POW_COOKIE "fossil-proofofwork" |
| 28 | |
| 29 | /* |
| 30 | ** Rewrite the current page with a robot squelch captcha and return 1. |
| 31 | ** |
| 32 | ** Or, if valid proof-of-work is present as either a query parameter or |
| 33 | ** as a cookie, then return 0. |
| @@ -61,14 +63,14 @@ | |
| 63 | h2 = (h2 % 900000000) + 100000000; |
| 64 | |
| 65 | /* If there is already a proof-of-work cookie with this value |
| 66 | ** that means that the user agent has already authenticated. |
| 67 | */ |
| 68 | z = P(POW_COOKIE); |
| 69 | if( z |
| 70 | && (atoi(z)==h1 || atoi(z)==h2) |
| 71 | && !cgi_is_qp(POW_COOKIE) ){ |
| 72 | return 0; |
| 73 | } |
| 74 | |
| 75 | /* Check for a proof query parameter. If found, that means that |
| 76 | ** the captcha has just now passed, so set the proof-of-work cookie |
| @@ -76,39 +78,45 @@ | |
| 78 | */ |
| 79 | z = P("proof"); |
| 80 | if( z |
| 81 | && (atoi(z)==h1 || atoi(z)==h2) |
| 82 | ){ |
| 83 | cgi_set_cookie(POW_COOKIE,z,"/",900); |
| 84 | return 0; |
| 85 | } |
| 86 | cgi_tag_query_parameter("proof"); |
| 87 | |
| 88 | /* Ask the client to present proof-of-work */ |
| 89 | cgi_reset_content(); |
| 90 | cgi_set_content_type("text/html"); |
| 91 | style_header("Browser Verification"); |
| 92 | @ <h1 id="x1">Checking to see if you are a robot<span id="x2"></span></h1> |
| 93 | @ <form method="GET"> |
| 94 | @ <p id="x3" style="visibility:hidden;">\ |
| 95 | @ Press <input type="submit" id="x5" value="Ok" focus> to continue</p> |
| 96 | cgi_query_parameters_to_hidden(); |
| 97 | @ <input id="x4" type="hidden" name="proof" value="0"> |
| 98 | @ </form> |
| 99 | @ <script nonce='%s(style_nonce())'> |
| 100 | @ function aaa(x){return document.getElementById(x);} |
| 101 | @ function bbb(h,a){ |
| 102 | @ aaa("x4").value=h |
| 103 | @ if((a%%75)==0){ |
| 104 | @ aaa("x2").textContent=aaa("x2").textContent+"."; |
| 105 | @ } |
| 106 | @ if(a>0){ |
| 107 | @ setTimeout(bbb,1,h+a,a-1); |
| 108 | @ }else{ |
| 109 | @ aaa("x3").style.visibility="visible"; |
| 110 | @ aaa("x2").textContent=""; |
| 111 | @ aaa("x1").textContent="All clear"; |
| 112 | @ aaa("x5").focus(); |
| 113 | @ } |
| 114 | @ } |
| 115 | k = 800 + h2%99; |
| 116 | h2 = (k*k + k)/2; |
| 117 | @ setTimeout(function(){bbb(%u(h1-h2),%u(k));},10); |
| 118 | @ </script> |
| 119 | style_finish_page(); |
| 120 | return 1; |
| 121 | } |
| 122 | |
| @@ -162,5 +170,48 @@ | |
| 170 | if( robot_proofofwork() ){ |
| 171 | return 1; |
| 172 | } |
| 173 | return 0; |
| 174 | } |
| 175 | |
| 176 | |
| 177 | /* |
| 178 | ** WEBPAGE: test-robotck |
| 179 | ** |
| 180 | ** Run the robot_restrict() function using the value of the "name=" |
| 181 | ** query parameter as an argument. Used for testing the robot_restrict() |
| 182 | ** logic. |
| 183 | ** |
| 184 | ** Whenever this page is successfully rendered (when it doesn't go to |
| 185 | ** the captcha) it deletes the proof-of-work cookie. So reloading the |
| 186 | ** page will reset the cookie and restart the verification. |
| 187 | */ |
| 188 | void robot_restrict_test_page(void){ |
| 189 | const char *zName = P("name"); |
| 190 | const char *zP1 = P("proof"); |
| 191 | const char *zP2 = P(POW_COOKIE); |
| 192 | const char *z; |
| 193 | if( zName==0 || zName[0]==0 ) zName = g.zPath; |
| 194 | login_check_credentials(); |
| 195 | if( !g.perm.Admin ){ login_needed(0); return; } |
| 196 | g.zLogin = 0; |
| 197 | if( robot_restrict(zName) ) return; |
| 198 | style_set_current_feature("test"); |
| 199 | style_header("robot_restrict() test"); |
| 200 | @ <h1>Captcha passed</h1> |
| 201 | @ |
| 202 | @ <p> |
| 203 | if( zP1 && zP1[0] ){ |
| 204 | @ proof=%h(zP1)<br> |
| 205 | } |
| 206 | if( zP2 && zP2[0] ){ |
| 207 | @ fossil_proofofwork=%h(zP2)<br> |
| 208 | cgi_set_cookie(POW_COOKIE,"",0,-1); |
| 209 | } |
| 210 | z = db_get("robot-restrict",robot_restrict_default()); |
| 211 | if( z && z[0] ){ |
| 212 | @ robot-restrict=%h(z)</br> |
| 213 | } |
| 214 | @ </p> |
| 215 | @ <p><a href="%R/test-robotck/%h(zName)">Retry</a> |
| 216 | style_finish_page(); |
| 217 | } |
| 218 |