From: Jack D. Pond Date: Fri, 4 Sep 2009 02:44:05 +0000 (+0000) Subject: bug 19646 Localization of img_auth.php - with enhancements X-Git-Tag: 1.31.0-rc.0~39943 X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=commitdiff_plain;h=81fad6027c7882939996e97bc4afbda952a50fe3;p=lhc%2Fweb%2Fwiklou.git bug 19646 Localization of img_auth.php - with enhancements https://bugzilla.wikimedia.org/show_bug.cgi?id=19646 1. Localize img_auth.php using core messages 2. Reorder checks to make sense (and eliminate redundancy)n 3. Add hook 'ImgAuthBeforeStream' to allow custom checking 4. Add globals wgImgAuthDetails, 5. Move all "wfDebugLog" into the rejection functions --- diff --git a/img_auth.php b/img_auth.php index cd8ec43a35..4764b780ef 100644 --- a/img_auth.php +++ b/img_auth.php @@ -3,122 +3,112 @@ /** * Image authorisation script * - * To use this: + * To use this, see http://www.mediawiki.org/wiki/Manual:Image_Authorization * * - Set $wgUploadDirectory to a non-public directory (not web accessible) * - Set $wgUploadPath to point to this file * - * Your server needs to support PATH_INFO; CGI-based configurations - * usually don't. + * Optional Parameters + * + * - Set $wgImgAuthDetails = true if you want the reason the access was denied messages to be displayed + * instead of just the 403 error (doesn't work on IE anyway), otherwise will only appear in error logs + * - Set $wgImgAuthPublicTest false if you don't want to just check and see if all are public + * must be set to false if using specific restrictions such as LockDown or NSFileRepo + * + * For security reasons, you usually don't want your user to know *why* access was denied, just that it was. + * If you want to change this, you can set $wgImgAuthDetails to 'true' in localsettings.php and it will give the user the reason + * why access was denied. + * + * Your server needs to support PATH_INFO; CGI-based configurations usually don't. * * @file - */ - + * + **/ + define( 'MW_NO_OUTPUT_COMPRESSION', 1 ); require_once( dirname( __FILE__ ) . '/includes/WebStart.php' ); wfProfileIn( 'img_auth.php' ); require_once( dirname( __FILE__ ) . '/includes/StreamFile.php' ); $perms = User::getGroupPermissions( array( '*' ) ); -if ( in_array( 'read', $perms, true ) ) { - wfDebugLog( 'img_auth', 'Public wiki' ); - wfPublicError(); -} + +// See if this is a public Wiki (no protections) +if ( $wgImgAuthPublicTest && in_array( 'read', $perms, true ) ) + wfForbidden('img-auth-accessdenied','img-auth-public'); // Extract path and image information -if( !isset( $_SERVER['PATH_INFO'] ) ) { - wfDebugLog( 'img_auth', 'Missing PATH_INFO' ); - wfForbidden(); -} +if( !isset( $_SERVER['PATH_INFO'] ) ) + wfForbidden('img-auth-accessdenied','img-auth-nopathinfo'); $path = $_SERVER['PATH_INFO']; $filename = realpath( $wgUploadDirectory . $_SERVER['PATH_INFO'] ); $realUpload = realpath( $wgUploadDirectory ); -wfDebugLog( 'img_auth', "\$path is {$path}" ); -wfDebugLog( 'img_auth', "\$filename is {$filename}" ); // Basic directory traversal check -if( substr( $filename, 0, strlen( $realUpload ) ) != $realUpload ) { - wfDebugLog( 'img_auth', 'Requested path not in upload directory' ); - wfForbidden(); -} +if( substr( $filename, 0, strlen( $realUpload ) ) != $realUpload ) + wfForbidden('img-auth-accessdenied','img-auth-notindir'); // Extract the file name and chop off the size specifier // (e.g. 120px-Foo.png => Foo.png) $name = wfBaseName( $path ); if( preg_match( '!\d+px-(.*)!i', $name, $m ) ) $name = $m[1]; -wfDebugLog( 'img_auth', "\$name is {$name}" ); + +// Check to see if the file exists +if( !file_exists( $filename ) ) + wfForbidden('img-auth-accessdenied','img-auth-nofile',htmlspecialchars($filename)); + +// Check to see if tried to access a directory +if( is_dir( $filename ) ) + wfForbidden('img-auth-accessdenied','img-auth-isdir',htmlspecialchars($filename)); + $title = Title::makeTitleSafe( NS_FILE, $name ); -if( !$title instanceof Title ) { - wfDebugLog( 'img_auth', "Unable to construct a valid Title from `{$name}`" ); - wfForbidden(); -} -if( !$title->userCanRead() ) { - wfDebugLog( 'img_auth', "User does not have access to read `{$name}`" ); - wfForbidden(); -} -$title = $title->getPrefixedText(); -// Check the whitelist if needed -if( !$wgUser->getId() && ( !is_array( $wgWhitelistRead ) || !in_array( $title, $wgWhitelistRead ) ) ) { - wfDebugLog( 'img_auth', "Not logged in and `{$title}` not in whitelist." ); - wfForbidden(); -} +// See if could create the title object +if( !$title instanceof Title ) + wfForbidden('img-auth-accessdenied','img-auth-badtitle',htmlspecialchars($name)); + +// Run hook +if (!wfRunHooks( 'ImgAuthBeforeStream', array( &$title, &$path, &$name, &$result ) ) ) + call_user_func_array('wfForbidden',merge_array(array($result[0],$result[1]),array_slice($result,2))); + +// Check user authorization for this title +// UserCanRead Checks Whitelist too +if( !$title->userCanRead() ) + wfForbidden('img-auth-accessdenied','img-auth-noread',htmlspecialchars($name)); -if( !file_exists( $filename ) ) { - wfDebugLog( 'img_auth', "`{$filename}` does not exist" ); - wfForbidden(); -} -if( is_dir( $filename ) ) { - wfDebugLog( 'img_auth', "`{$filename}` is a directory" ); - wfForbidden(); -} // Stream the requested file -wfDebugLog( 'img_auth', "Streaming `{$filename}`" ); +wfDebugLog( 'img_auth', "Streaming `".htmlspecialchars($filename)."`." ); wfStreamFile( $filename, array( 'Cache-Control: private', 'Vary: Cookie' ) ); wfLogProfilingData(); /** - * Issue a standard HTTP 403 Forbidden header and a basic - * error message, then end the script + * Issue a standard HTTP 403 Forbidden header ($msg1-a message index, not a message) and an + * error message ($msg2, also a message index), (both required) then end the script + * subsequent arguments to $msg2 will be passed as parameters only for replacing in $msg2 */ -function wfForbidden() { +function wfForbidden($msg1,$msg2) { + global $wgImgAuthDetails; + $args = func_get_args(); + array_shift( $args ); + array_shift( $args ); + $MsgHdr = wfMsgHTML($msg1); + $detailMsg = call_user_func_array('wfMsgHTML',array_merge(array($wgImgAuthDetails ? $msg2 : 'badaccess-group0'),$args)); + wfDebugLog('img_auth', "wfForbidden Hdr:".wfMsgExt( $msg1, array('language' => 'en'))." Msg: ". + call_user_func_array('wfMsgExt',array_merge( array($msg2, array('language' => 'en')),$args))); header( 'HTTP/1.0 403 Forbidden' ); - header( 'Vary: Cookie' ); + header( 'Cache-Control: no-cache' ); header( 'Content-Type: text/html; charset=utf-8' ); echo << -

Access Denied

-

You need to log in to access files on this server.

+

$MsgHdr

+

$detailMsg

ENDS; wfLogProfilingData(); exit(); } - -/** - * Show a 403 error for use when the wiki is public - */ -function wfPublicError() { - header( 'HTTP/1.0 403 Forbidden' ); - header( 'Content-Type: text/html; charset=utf-8' ); - echo << - -

Access Denied

-

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 in -this case. -

- - -ENDS; - wfLogProfilingData(); - exit; -} - diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 985a6e4f93..a696564221 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -191,6 +191,14 @@ $wgFileStore['deleted']['directory'] = false;///< Defaults to $wgUploadDirectory $wgFileStore['deleted']['url'] = null; ///< Private $wgFileStore['deleted']['hash'] = 3; ///< 3-level subdirectory split + +/** + * used only for img_auth script - see [[Image Authorization]] + */ +$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 +$wgImgAuthPublicTest = true; ///< defaults to true - if public read is turned on, no need for img_auth, config error unless other access is used + + /**@{ * File repository structures * @@ -281,7 +289,6 @@ $wgForeignFileRepos = array(); */ $wgLegalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+"; - /** * The external URL protocols */ diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 88714585f6..e489ae7dfb 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -2144,6 +2144,19 @@ If the problem persists, contact an [[Special:ListUsers/sysop|administrator]].', 'upload-unknown-size' => 'Unknown size', 'upload-http-error' => 'An HTTP error occured: $1', +#img_auth script messages +'img-auth-accessdenied' => "Access Denied", +'img-auth-desc' => 'Image authorisation script', +'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.", +'img-auth-notindir' => "Requested path is not in the configured upload directory.", +'img-auth-badtitle' => "Unable to construct a valid title from `$1`.", +'img-auth-nologinnWL' => "You are not logged in and `$1` not in whitelist.", +'img-auth-nofile' => "File `$1` does not exist.", +'img-auth-isdir' => "you are trying to access a directory`$1`. Only file access is allowed.", +'img-auth-streaming' => "Streaming `$1`.", +'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.", +'img-auth-noread' => "User does not have access to read `$1`.", + # Some likely curl errors. More could be added from 'upload-curl-error6' => 'Could not reach URL', 'upload-curl-error6-text' => 'The URL provided could not be reached. diff --git a/languages/messages/MessagesQqq.php b/languages/messages/MessagesQqq.php index 3c56d551cc..52b86f0e0a 100644 --- a/languages/messages/MessagesQqq.php +++ b/languages/messages/MessagesQqq.php @@ -2641,6 +2641,19 @@ The message appears after the name of the patroller.', * $1 is a date (example: ''19 March 2008'') * $2 is a time (example: ''12:15'')", +#img_auth script messages +'img-auth-desc' => '[[Manual:Image Authorization]] script, see http://www.mediawiki.org/wiki/Manual:Image_Authorization', +'img-auth-accessdenied' => "[[Manual:Image Authorization]] Access Denied", +'img-auth-nopathinfo' => "[[Manual:Image Authorization]] Missing PATH_INFO - see english description", +'img-auth-notindir' => "[[Manual:Image Authorization]] when the specified path is not in upload directory.", +'img-auth-badtitle' => "[[Manual:Image Authorization]] bad title, $1 is the invalid title", +'img-auth-nologinnWL' => "[[Manual:Image Authorization]] logged in and file not whitelisted. $1 is the file not in whitelist.", +'img-auth-nofile' => "[[Manual:Image Authorization]] non existent file, $1 is the file that does not exist.", +'img-auth-isdir' => "[[Manual:Image Authorization]] trying to access a directory instead of a file, $1 is the directory.", +'img-auth-streaming' => "[[Manual:Image Authorization]] is now streaming file specified by $1.", +'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", +'img-auth-noread' => "[[Manual:Image Authorization]] User does not have access to read file, $1 is the file", + # Video information, used by Language::formatTimePeriod() to format lengths in the above messages 'seconds-abbrev' => '{{optional}}', 'minutes-abbrev' => '{{optional}}', diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index 234be98809..756eec424d 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -327,6 +327,17 @@ $wgMessageStructure = array( 'anonnotice', 'newsectionheaderdefaultlevel', 'red-link-title', + 'img-auth-accessdenied', + 'img-auth-desc', + 'img-auth-nopathinfo', + 'img-auth-notindir', + 'img-auth-badtitle', + 'img-auth-nologinnWL', + 'img-auth-nofile', + 'img-auth-isdir', + 'img-auth-streaming', + 'img-auth-public', + 'img-auth-noread', ), 'nstab' => array( 'nstab-main',