Extension:SimpleSecurity

This is a simple solution involving a single snippet of code to be included from the LocalSettings.php file, it's been tested on version 1.6.7 and 1.9.3, and is being maintained at. It allows security directives to be placed in an article which affect the articles permissions, but are not rendered. The security directives are similar to how category links work in that they perform a function but do not render on the page. It's not a very robust (see below for current flaws), and there's no encryption of data, but it's fine for general purpose use, and very easy to install.

Syntax & usage examples

 * {{#security:actions|users/groups}}

Actions and users/groups are both comma-separated lists. Allowed actions are view, edit, history, move, delete, raw, watch/unwatch and protect. Users names start with an uppercase letter, group names are all lowercase. Assign users to groups using the usual Special:Userrights page. Following are a few examples:
 * {{#security:*|admin,Fred}}
 * {{#security:edit,delete|Sam,Fred}}
 * {{#security:view,history|staff,consultants}}</tt>

Here's an example of using a pair of directives to allow everyone view-only access to an article
 * {</tt>{#security:*|sysop}}</tt> {</tt>{#security:view|*}}</tt>

Notes:
 * The syntax has changed in version 2.0 from square-brackets to curly-braces
 * The * refers to any action and allows one to specify default permissions. The defaults will be overridden if another security link matches the action specifically.
 * You can change the name used for security links with the $wgSecurityMagic global variable, by default it is "Security".
 * In MediaWiki version 1.6.x, the magic words must include the hash (#) symbol explicitly if you want that syntax. In version 1.9.x the hash format is mandatory and implicit, and so must not be included in the global magic-names variables.

Groups & rights
The groups used in the security links refer to the usual MediaWiki groups managed in the Special:Userrights page. As of MediaWiki version 1.6.x group management only allows users to be added or removed from existing groups, but adding or removing the available groups needs to be done by changing either the LocalSettings.php or Security.php file/article. The following small snippet of code can be added instead which allows the available groups to be read from a bullet list in an article called Groups. $groups = new Article(Title::newFromText('Groups')); if (preg_match_all('/^\\*\\s*(.+?)\\s*$/m',$groups->getContent,$match)) foreach($match[1] as $group) $wgGroupPermissions[$group] = array;

Inheriting article security from categories
Security settings can be assigned to articles in a category-wide way simply by adding the security link to the category article. Articles automatically inherit the security settings exhibited by any of the categories they're in. If an article also contains its own security links, they will override the inherited ones.

You can use an explanation mark after the hash (a shebang) in a category page's security links to prevent them from being inherited by the contained articles, for example:
 * {</tt>{#!Security:history|timelord}}</tt>

This will mean that you need to be in the timelord group to access the history of the category page, but access to the history of any of the articles in the category is unaffected.

Notes:
 * You can enable/disable inhertited security with the $wgSecurityInheritable global variable
 * You can change the name used for recursive security links with the $wgSecurityMagicNoi global variable, by default it is the same name as the normal security links but with a preceeding asterisk.
 * Security inheritence is not recursive, i.e. any security that a category inherits will not be passed on to the articles it contains, only the security links it exhibits itself will be passed down (except those with preceeding asterisk as described above).

Security-based conditions
In version 3.0 a new feature has been added allowing content to be rendered depending on a security query. Here's an example which makes a message render only if the user can edit the main page page.

You can also add a forth parameter which will render if the condition is not satisfied. This functionality was designed to work with Extension:Tree view to make trees filter some of its nodes out depending on user groups and permissions. The tree view extension helps this by not rendering any empty nodes.

Security on images & files
<font color=#cc0000>Note: this feature was disabled in 3.0 but has been included again now in 3.1 If security links are placed into articles in the Image:</tt> namespace, the code can prevent the images or its thumbnails from being returned to the client if they don't have readable permission. This feature requires Apache's mod-rewrite to be running and have the following condition and rule (update to your won wiki's path if necessary). RewriteCond %{REQUEST_URI} ^/wiki/images/.+ RewriteRule ^/wiki/images/(.+) /wiki/index.php/Download/$1 [L] This allows all requests into the images structure to be redirected to an article title which is intercepted by the security code and validated against security before the file is sent to the client. If the requested file is refused, then the file specified in the $wgSecurityDenyImage</tt> is returned in its place.

Installation
The code is a single snippet available from SimpleSecurity.php which you must should as a file of the same name in your extensions directory. You then include this from your LocalSettings.php file as follows: include('extensions/SimpleSecurity.php'); If you're using MediaWiki 1.6.x but want the same hash syntax as normal parser functions, add the following lines after the include. $wgSecurityMagic = '#security'; $wgSecurityMagicNoi = '#!security'; $wgSecurityMagicIf = '#ifusercan';

Template examples
Here's an example of each of the templates which you can refine to you're own needs:

Template:Action not permitted
<p style="font-size:125%;color:#c00;">Sorry, action not permitted! Your user rights do not permit the ' action to be performed on the ' article.

Dependencies
You'll need to install Apache's mod-rewrite for security on images and files to work. Also, the security.php code refers to a number of other articles. The article names and their purpose are listed below, and they link to the Organic Design wiki where they're maintained.

Testing
This extension has been tested in the following environments:
 * works with PHP 4.x and PHP 5.x
 * works with MediaWiki 1.6.7
 * works with MediaWiki 1.9.3

Security holes
There is a list of flaws often found in MediaWiki security extensions here, and I've included the ones that this extension currently suffers from below. There is a solution to these issues in progress.
 * Search article: Do you get results with partially displayed text? See also 8825
 * Atom/RSS feeds: Does the article get delivered? There are two feeds, one in the Recent changes special pages and other on the page history. For extensions using the userCan hook, this has been fixed in MW 1.10, 19944.
 * XML export (Special:Export): Is it possible to export the contents of a protected page? For extensions using the userCan hook, this has been fixed in MW 1.10, 19935.
 * Diff: Can a direct link to a page diff be used to show text from a protected page? For extensions using the userCan hook, this should be OK on recent versions of MediaWiki.

Changes in version 3.1

 * The file/image security had to be re-implemented to work with the version 3.0 and is working again now.
 * Two additional gloals were added to enable/disable file-based security, and to specify a file to return if the requested one is denied.
 * Checks if encoding type is gzip and gzips before sending for file security

Changes in version 3.0

 * The whole thing has been rewritten based on the parser functions extension so that it works in accord with the MediaWiki object-oriented convensions and works across the MediaWiki versions better.
 * It now installs in the same way as other extensions.
 * The #ifusercan function was added for allowing rendered content to be dependent on permissions

Changes in version 2.0
The major difference in this version 2.0 is that the newer version has changed the syntax of the security links from square brackets to braces. The problem with the brackets method is that it required the code to extract and remove the security information from the article using a pattern match and replace on the text, which is very inefficient. Using braces allows a tighter integration with the MediaWiki parser so that the parser itself calls a function to process the security directives as it comes across them.

The second difference is that the security validation is done on the ArticleAfterFetchContent hook so that the security is assessed for transcluded articles as well as the main title article. I thought this would also fix the security holes listed above, but those still need a little more work!

New solution in progress to fix remaining security flaws
Fixing the remaining flaws of search, XML-exports and diff's containing information which should be inaccessible is quite a problem because those functions are obtaining article content with their own SQL queries, rather than fetching the content via the $wgArticle object. XmlWiki overcomes the problems by intercepting and filtering the rendered content, but that method is a hack and doesn't protect against other extensions which render differently structured content.

What's really needed is a way to intercept the database rows as they're retrieved for rendering, but there are no official hooks in that level of the MediaWiki code (not in version 1.6.x anyway). But I've found a method of dynamically adding a new hook to the DatabaseXXX::fetchObject method which is the method called by search, XML-export and RSS-feeds (and probably anything else which plans on iterating through the results of an SQL query).

This hook has been created and tested on MediaWiki 1.6.8 and is called DatabaseFetchObject. It will be included in the security.php code, but has also been added as a separate extension since other people may find it useful for other purposes too.