Extension:SimpleSecurity

This is a simple solution involving a single snippet of code to be included from the index.php script, it's only been tested on version 1.6.7, and is being maintained in MediaWiki Security. 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 $wgSecurityName global variable, by default it is "Security".

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->fetchContent(0,false,false),$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 a preceeding asterisk 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 $wgSecurityDontInheritName 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 on images & files
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.

Installation
The code is a single snippet available from security.php which you can either save as a file or keep as an article in your wiki. The code you insert into your index.php</tt> file is just after the $action</tt> and $title</tt> variables are set which look like this: $action = $wgRequest->getVal( 'action', 'view' ); $title = $wgRequest->getVal( 'title' ); Add one of the snippets of code below depending on whether your security snippet is a file or an article, include('extensions/security.php');
 * 1) Query string fields
 * Using a file placed into the extensions directory

$tmp = new Article( Title::newFromText('security.php') ); eval($tmp->getContent);
 * Using an 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.
 * Download requests for images with security are logged in the Download log article
 * The log entry format is Template:Log entry
 * Violation of security renders using Template:Action not permitted
 * Secruity information is rendered below secure articles using Template:Security info which includes Image:Padlock.png

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
 * Does not yet work in 1.9.3 - I can't get $parser->setFunctionHook to work in this version of MediaWiki, any ideas anyone?

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 from version 1.0
The major difference between version 1.0 and 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.