Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -327,6 +327,17 @@ |
328 | 328 | 'anonnotice', |
329 | 329 | 'newsectionheaderdefaultlevel', |
330 | 330 | 'red-link-title', |
| 331 | + 'img-auth-accessdenied', |
| 332 | + 'img-auth-desc', |
| 333 | + 'img-auth-nopathinfo', |
| 334 | + 'img-auth-notindir', |
| 335 | + 'img-auth-badtitle', |
| 336 | + 'img-auth-nologinnWL', |
| 337 | + 'img-auth-nofile', |
| 338 | + 'img-auth-isdir', |
| 339 | + 'img-auth-streaming', |
| 340 | + 'img-auth-public', |
| 341 | + 'img-auth-noread', |
331 | 342 | ), |
332 | 343 | 'nstab' => array( |
333 | 344 | 'nstab-main', |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -191,6 +191,14 @@ |
192 | 192 | $wgFileStore['deleted']['url'] = null; ///< Private |
193 | 193 | $wgFileStore['deleted']['hash'] = 3; ///< 3-level subdirectory split |
194 | 194 | |
| 195 | + |
| 196 | +/** |
| 197 | + * used only for img_auth script - see [[Image Authorization]] |
| 198 | + */ |
| 199 | +$wgImgAuthDetails = false; ///< defaults to false - only set to true if you use img_auth and want the user to see details on why access failed |
| 200 | +$wgImgAuthPublicTest = true; ///< defaults to true - if public read is turned on, no need for img_auth, config error unless other access is used |
| 201 | + |
| 202 | + |
195 | 203 | /**@{ |
196 | 204 | * File repository structures |
197 | 205 | * |
— | — | @@ -281,7 +289,6 @@ |
282 | 290 | */ |
283 | 291 | $wgLegalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+"; |
284 | 292 | |
285 | | - |
286 | 293 | /** |
287 | 294 | * The external URL protocols |
288 | 295 | */ |
Index: trunk/phase3/img_auth.php |
— | — | @@ -3,122 +3,112 @@ |
4 | 4 | /** |
5 | 5 | * Image authorisation script |
6 | 6 | * |
7 | | - * To use this: |
| 7 | + * To use this, see http://www.mediawiki.org/wiki/Manual:Image_Authorization |
8 | 8 | * |
9 | 9 | * - Set $wgUploadDirectory to a non-public directory (not web accessible) |
10 | 10 | * - Set $wgUploadPath to point to this file |
11 | 11 | * |
12 | | - * Your server needs to support PATH_INFO; CGI-based configurations |
13 | | - * usually don't. |
| 12 | + * Optional Parameters |
14 | 13 | * |
| 14 | + * - Set $wgImgAuthDetails = true if you want the reason the access was denied messages to be displayed |
| 15 | + * instead of just the 403 error (doesn't work on IE anyway), otherwise will only appear in error logs |
| 16 | + * - Set $wgImgAuthPublicTest false if you don't want to just check and see if all are public |
| 17 | + * must be set to false if using specific restrictions such as LockDown or NSFileRepo |
| 18 | + * |
| 19 | + * For security reasons, you usually don't want your user to know *why* access was denied, just that it was. |
| 20 | + * If you want to change this, you can set $wgImgAuthDetails to 'true' in localsettings.php and it will give the user the reason |
| 21 | + * why access was denied. |
| 22 | + * |
| 23 | + * Your server needs to support PATH_INFO; CGI-based configurations usually don't. |
| 24 | + * |
15 | 25 | * @file |
16 | | - */ |
17 | | - |
| 26 | + * |
| 27 | + **/ |
| 28 | + |
18 | 29 | define( 'MW_NO_OUTPUT_COMPRESSION', 1 ); |
19 | 30 | require_once( dirname( __FILE__ ) . '/includes/WebStart.php' ); |
20 | 31 | wfProfileIn( 'img_auth.php' ); |
21 | 32 | require_once( dirname( __FILE__ ) . '/includes/StreamFile.php' ); |
22 | 33 | |
23 | 34 | $perms = User::getGroupPermissions( array( '*' ) ); |
24 | | -if ( in_array( 'read', $perms, true ) ) { |
25 | | - wfDebugLog( 'img_auth', 'Public wiki' ); |
26 | | - wfPublicError(); |
27 | | -} |
28 | 35 | |
| 36 | +// See if this is a public Wiki (no protections) |
| 37 | +if ( $wgImgAuthPublicTest && in_array( 'read', $perms, true ) ) |
| 38 | + wfForbidden('img-auth-accessdenied','img-auth-public'); |
| 39 | + |
29 | 40 | // Extract path and image information |
30 | | -if( !isset( $_SERVER['PATH_INFO'] ) ) { |
31 | | - wfDebugLog( 'img_auth', 'Missing PATH_INFO' ); |
32 | | - wfForbidden(); |
33 | | -} |
| 41 | +if( !isset( $_SERVER['PATH_INFO'] ) ) |
| 42 | + wfForbidden('img-auth-accessdenied','img-auth-nopathinfo'); |
34 | 43 | |
35 | 44 | $path = $_SERVER['PATH_INFO']; |
36 | 45 | $filename = realpath( $wgUploadDirectory . $_SERVER['PATH_INFO'] ); |
37 | 46 | $realUpload = realpath( $wgUploadDirectory ); |
38 | | -wfDebugLog( 'img_auth', "\$path is {$path}" ); |
39 | | -wfDebugLog( 'img_auth', "\$filename is {$filename}" ); |
40 | 47 | |
41 | 48 | // Basic directory traversal check |
42 | | -if( substr( $filename, 0, strlen( $realUpload ) ) != $realUpload ) { |
43 | | - wfDebugLog( 'img_auth', 'Requested path not in upload directory' ); |
44 | | - wfForbidden(); |
45 | | -} |
| 49 | +if( substr( $filename, 0, strlen( $realUpload ) ) != $realUpload ) |
| 50 | + wfForbidden('img-auth-accessdenied','img-auth-notindir'); |
46 | 51 | |
47 | 52 | // Extract the file name and chop off the size specifier |
48 | 53 | // (e.g. 120px-Foo.png => Foo.png) |
49 | 54 | $name = wfBaseName( $path ); |
50 | 55 | if( preg_match( '!\d+px-(.*)!i', $name, $m ) ) |
51 | 56 | $name = $m[1]; |
52 | | -wfDebugLog( 'img_auth', "\$name is {$name}" ); |
53 | 57 | |
| 58 | +// Check to see if the file exists |
| 59 | +if( !file_exists( $filename ) ) |
| 60 | + wfForbidden('img-auth-accessdenied','img-auth-nofile',htmlspecialchars($filename)); |
| 61 | + |
| 62 | +// Check to see if tried to access a directory |
| 63 | +if( is_dir( $filename ) ) |
| 64 | + wfForbidden('img-auth-accessdenied','img-auth-isdir',htmlspecialchars($filename)); |
| 65 | + |
| 66 | + |
54 | 67 | $title = Title::makeTitleSafe( NS_FILE, $name ); |
55 | | -if( !$title instanceof Title ) { |
56 | | - wfDebugLog( 'img_auth', "Unable to construct a valid Title from `{$name}`" ); |
57 | | - wfForbidden(); |
58 | | -} |
59 | | -if( !$title->userCanRead() ) { |
60 | | - wfDebugLog( 'img_auth', "User does not have access to read `{$name}`" ); |
61 | | - wfForbidden(); |
62 | | -} |
63 | | -$title = $title->getPrefixedText(); |
64 | 68 | |
65 | | -// Check the whitelist if needed |
66 | | -if( !$wgUser->getId() && ( !is_array( $wgWhitelistRead ) || !in_array( $title, $wgWhitelistRead ) ) ) { |
67 | | - wfDebugLog( 'img_auth', "Not logged in and `{$title}` not in whitelist." ); |
68 | | - wfForbidden(); |
69 | | -} |
| 69 | +// See if could create the title object |
| 70 | +if( !$title instanceof Title ) |
| 71 | + wfForbidden('img-auth-accessdenied','img-auth-badtitle',htmlspecialchars($name)); |
70 | 72 | |
71 | | -if( !file_exists( $filename ) ) { |
72 | | - wfDebugLog( 'img_auth', "`{$filename}` does not exist" ); |
73 | | - wfForbidden(); |
74 | | -} |
75 | | -if( is_dir( $filename ) ) { |
76 | | - wfDebugLog( 'img_auth', "`{$filename}` is a directory" ); |
77 | | - wfForbidden(); |
78 | | -} |
| 73 | +// Run hook |
| 74 | +if (!wfRunHooks( 'ImgAuthBeforeStream', array( &$title, &$path, &$name, &$result ) ) ) |
| 75 | + call_user_func_array('wfForbidden',merge_array(array($result[0],$result[1]),array_slice($result,2))); |
| 76 | + |
| 77 | +// Check user authorization for this title |
| 78 | +// UserCanRead Checks Whitelist too |
| 79 | +if( !$title->userCanRead() ) |
| 80 | + wfForbidden('img-auth-accessdenied','img-auth-noread',htmlspecialchars($name)); |
79 | 81 | |
| 82 | + |
80 | 83 | // Stream the requested file |
81 | | -wfDebugLog( 'img_auth', "Streaming `{$filename}`" ); |
| 84 | +wfDebugLog( 'img_auth', "Streaming `".htmlspecialchars($filename)."`." ); |
82 | 85 | wfStreamFile( $filename, array( 'Cache-Control: private', 'Vary: Cookie' ) ); |
83 | 86 | wfLogProfilingData(); |
84 | 87 | |
85 | 88 | /** |
86 | | - * Issue a standard HTTP 403 Forbidden header and a basic |
87 | | - * error message, then end the script |
| 89 | + * Issue a standard HTTP 403 Forbidden header ($msg1-a message index, not a message) and an |
| 90 | + * error message ($msg2, also a message index), (both required) then end the script |
| 91 | + * subsequent arguments to $msg2 will be passed as parameters only for replacing in $msg2 |
88 | 92 | */ |
89 | | -function wfForbidden() { |
| 93 | +function wfForbidden($msg1,$msg2) { |
| 94 | + global $wgImgAuthDetails; |
| 95 | + $args = func_get_args(); |
| 96 | + array_shift( $args ); |
| 97 | + array_shift( $args ); |
| 98 | + $MsgHdr = wfMsgHTML($msg1); |
| 99 | + $detailMsg = call_user_func_array('wfMsgHTML',array_merge(array($wgImgAuthDetails ? $msg2 : 'badaccess-group0'),$args)); |
| 100 | + wfDebugLog('img_auth', "wfForbidden Hdr:".wfMsgExt( $msg1, array('language' => 'en'))." Msg: ". |
| 101 | + call_user_func_array('wfMsgExt',array_merge( array($msg2, array('language' => 'en')),$args))); |
90 | 102 | header( 'HTTP/1.0 403 Forbidden' ); |
91 | | - header( 'Vary: Cookie' ); |
| 103 | + header( 'Cache-Control: no-cache' ); |
92 | 104 | header( 'Content-Type: text/html; charset=utf-8' ); |
93 | 105 | echo <<<ENDS |
94 | 106 | <html> |
95 | 107 | <body> |
96 | | -<h1>Access Denied</h1> |
97 | | -<p>You need to log in to access files on this server.</p> |
| 108 | +<h1>$MsgHdr</h1> |
| 109 | +<p>$detailMsg</p> |
98 | 110 | </body> |
99 | 111 | </html> |
100 | 112 | ENDS; |
101 | 113 | wfLogProfilingData(); |
102 | 114 | exit(); |
103 | 115 | } |
104 | | - |
105 | | -/** |
106 | | - * Show a 403 error for use when the wiki is public |
107 | | - */ |
108 | | -function wfPublicError() { |
109 | | - header( 'HTTP/1.0 403 Forbidden' ); |
110 | | - header( 'Content-Type: text/html; charset=utf-8' ); |
111 | | - echo <<<ENDS |
112 | | -<html> |
113 | | -<body> |
114 | | -<h1>Access Denied</h1> |
115 | | -<p>The function of img_auth.php is to output files from a private wiki. This wiki |
116 | | -is configured as a public wiki. For optimal security, img_auth.php is disabled in |
117 | | -this case. |
118 | | -</p> |
119 | | -</body> |
120 | | -</html> |
121 | | -ENDS; |
122 | | - wfLogProfilingData(); |
123 | | - exit; |
124 | | -} |
125 | | - |
Index: trunk/phase3/languages/messages/MessagesQqq.php |
— | — | @@ -2641,6 +2641,19 @@ |
2642 | 2642 | * $1 is a date (example: ''19 March 2008'') |
2643 | 2643 | * $2 is a time (example: ''12:15'')", |
2644 | 2644 | |
| 2645 | +#img_auth script messages |
| 2646 | +'img-auth-desc' => '[[Manual:Image Authorization]] script, see http://www.mediawiki.org/wiki/Manual:Image_Authorization', |
| 2647 | +'img-auth-accessdenied' => "[[Manual:Image Authorization]] Access Denied", |
| 2648 | +'img-auth-nopathinfo' => "[[Manual:Image Authorization]] Missing PATH_INFO - see english description", |
| 2649 | +'img-auth-notindir' => "[[Manual:Image Authorization]] when the specified path is not in upload directory.", |
| 2650 | +'img-auth-badtitle' => "[[Manual:Image Authorization]] bad title, $1 is the invalid title", |
| 2651 | +'img-auth-nologinnWL' => "[[Manual:Image Authorization]] logged in and file not whitelisted. $1 is the file not in whitelist.", |
| 2652 | +'img-auth-nofile' => "[[Manual:Image Authorization]] non existent file, $1 is the file that does not exist.", |
| 2653 | +'img-auth-isdir' => "[[Manual:Image Authorization]] trying to access a directory instead of a file, $1 is the directory.", |
| 2654 | +'img-auth-streaming' => "[[Manual:Image Authorization]] is now streaming file specified by $1.", |
| 2655 | +'img-auth-public' => "[[Manual:Image Authorization]] an error message when the admin has configured the wiki to be a public wiki, but is using img_auth script - normally this is a configuration error, except when special restriction extensions are used", |
| 2656 | +'img-auth-noread' => "[[Manual:Image Authorization]] User does not have access to read file, $1 is the file", |
| 2657 | + |
2645 | 2658 | # Video information, used by Language::formatTimePeriod() to format lengths in the above messages |
2646 | 2659 | 'seconds-abbrev' => '{{optional}}', |
2647 | 2660 | 'minutes-abbrev' => '{{optional}}', |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -2144,6 +2144,19 @@ |
2145 | 2145 | 'upload-unknown-size' => 'Unknown size', |
2146 | 2146 | 'upload-http-error' => 'An HTTP error occured: $1', |
2147 | 2147 | |
| 2148 | +#img_auth script messages |
| 2149 | +'img-auth-accessdenied' => "Access Denied", |
| 2150 | +'img-auth-desc' => 'Image authorisation script', |
| 2151 | +'img-auth-nopathinfo' => "Missing PATH_INFO. Your server is not set up to pass this information - may be CGI-based and can't support img_auth. See http://www.mediawiki.org/wiki/Manual:Image_Authorization.", |
| 2152 | +'img-auth-notindir' => "Requested path is not in the configured upload directory.", |
| 2153 | +'img-auth-badtitle' => "Unable to construct a valid title from `$1`.", |
| 2154 | +'img-auth-nologinnWL' => "You are not logged in and `$1` not in whitelist.", |
| 2155 | +'img-auth-nofile' => "File `$1` does not exist.", |
| 2156 | +'img-auth-isdir' => "you are trying to access a directory`$1`. Only file access is allowed.", |
| 2157 | +'img-auth-streaming' => "Streaming `$1`.", |
| 2158 | +'img-auth-public' => "The function of img_auth.php is to output files from a private wiki. This wiki is configured as a public wiki. For optimal security, img_auth.php is disabled for this case.", |
| 2159 | +'img-auth-noread' => "User does not have access to read `$1`.", |
| 2160 | + |
2148 | 2161 | # Some likely curl errors. More could be added from <http://curl.haxx.se/libcurl/c/libcurl-errors.html> |
2149 | 2162 | 'upload-curl-error6' => 'Could not reach URL', |
2150 | 2163 | 'upload-curl-error6-text' => 'The URL provided could not be reached. |