From 94818a30e1dd91b479db8c159842d9339f39689c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Schneider?= Date: Fri, 22 Mar 2013 12:18:45 +0100 Subject: [PATCH] Initial import : add module mon_agglo_exportjson and simplesamlphp_auth --- .../mon_agglo_exportjson.info | 6 + .../mon_agglo_exportjson.install | 13 + .../mon_agglo_exportjson.module | 60 + .../templates/news_lists.tpl.php | 5 + drupal/simplesamlphp_auth/LICENSE.txt | 339 ++++++ drupal/simplesamlphp_auth/README.txt | 56 + .../simplesamlphp/config/authsources.php | 334 +++++ .../simplesamlphp/config/config.php | 650 ++++++++++ .../metadata/saml20-idp-remote.php | 53 + .../simplesamlphp_auth.info | 12 + .../simplesamlphp_auth.install | 49 + .../simplesamlphp_auth.module | 1074 +++++++++++++++++ .../simplesamlphp_auth.rules.inc | 34 + 13 files changed, 2685 insertions(+) create mode 100644 drupal/mon_agglo_exportjson/mon_agglo_exportjson.info create mode 100644 drupal/mon_agglo_exportjson/mon_agglo_exportjson.install create mode 100644 drupal/mon_agglo_exportjson/mon_agglo_exportjson.module create mode 100644 drupal/mon_agglo_exportjson/templates/news_lists.tpl.php create mode 100644 drupal/simplesamlphp_auth/LICENSE.txt create mode 100644 drupal/simplesamlphp_auth/README.txt create mode 100644 drupal/simplesamlphp_auth/simplesamlphp/config/authsources.php create mode 100644 drupal/simplesamlphp_auth/simplesamlphp/config/config.php create mode 100644 drupal/simplesamlphp_auth/simplesamlphp/metadata/saml20-idp-remote.php create mode 100644 drupal/simplesamlphp_auth/simplesamlphp_auth.info create mode 100644 drupal/simplesamlphp_auth/simplesamlphp_auth.install create mode 100644 drupal/simplesamlphp_auth/simplesamlphp_auth.module create mode 100644 drupal/simplesamlphp_auth/simplesamlphp_auth.rules.inc diff --git a/drupal/mon_agglo_exportjson/mon_agglo_exportjson.info b/drupal/mon_agglo_exportjson/mon_agglo_exportjson.info new file mode 100644 index 0000000..3b5cf45 --- /dev/null +++ b/drupal/mon_agglo_exportjson/mon_agglo_exportjson.info @@ -0,0 +1,6 @@ +name = Export data into json +description = Gére l'export des newsletters en json + +package = entrouvert +version = 7.x-1.0dev +core = 7.x diff --git a/drupal/mon_agglo_exportjson/mon_agglo_exportjson.install b/drupal/mon_agglo_exportjson/mon_agglo_exportjson.install new file mode 100644 index 0000000..0279222 --- /dev/null +++ b/drupal/mon_agglo_exportjson/mon_agglo_exportjson.install @@ -0,0 +1,13 @@ + 'newsletter_export_view', + 'access callback' => TRUE, + 'access arguments' => array('Export json des newsletters'), + ); + return $items; +} + + +function _get_newsletters($user) { + + $allowedNewsletters = array("372","373","374","375","376","377"); + + $hashAlgo = 'sha1'; + $hashSalt = 'mykey'; + + $form = array(); + + $paramsArray = array( + 'action' => 'read', + 'email' => $user->mail, + 'hash' => hash($hashAlgo, $hashSalt.$user->mail) + ); + + $results = _mon_agglo_cron_do_post('https://emailingeco.montpellier-agglo.com/ws/index.php', $paramsArray, 'http://preview-preprod.montpellier-agglo.com'); + + + if(strpos($results['header'], 'HTTP/1.1 200 OK') !== FALSE) + { + $content = json_decode($results['content']); + $newsletters = array(); + foreach ($content->newsletter as $id => $name) { + if (in_array($id, $allowedNewsletters)) + { + if (in_array($id, $content->subscriptions)) + $newsletters[$name] = True; + else + $newsletters[$name] = False; + } + } + $content = array('uid' => $user->uid, 'newsletters' => $newsletters); + return $content; + } +} + +function newsletter_export_view() { + if (!array_key_exists('nameid', $_GET)) + return drupal_json_output(array("error" => "You must set param nameid")); + + $nameid = $_GET['nameid']; + $ext_user = user_external_load($nameid); + if (!$ext_user) + return drupal_json_output(array("error" => "$nameid user not found")); + return drupal_json_output(_get_newsletters($ext_user)); +} + diff --git a/drupal/mon_agglo_exportjson/templates/news_lists.tpl.php b/drupal/mon_agglo_exportjson/templates/news_lists.tpl.php new file mode 100644 index 0000000..ca10125 --- /dev/null +++ b/drupal/mon_agglo_exportjson/templates/news_lists.tpl.php @@ -0,0 +1,5 @@ +
+ + + +
\ No newline at end of file diff --git a/drupal/simplesamlphp_auth/LICENSE.txt b/drupal/simplesamlphp_auth/LICENSE.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/drupal/simplesamlphp_auth/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/drupal/simplesamlphp_auth/README.txt b/drupal/simplesamlphp_auth/README.txt new file mode 100644 index 0000000..29b1725 --- /dev/null +++ b/drupal/simplesamlphp_auth/README.txt @@ -0,0 +1,56 @@ +-- SUMMARY -- + +The simplesamlphp_auth module makes it possible for Drupal to support SAML for +authentication of users. The module will auto-provision user accounts into +Drupal if you want it to. It can also dynamically assign Drupal roles based on +identity attribute values. + + +-- PREREQUISITES -- + +1) You must have SimpleSAMLphp installed and configured as a working service + point (SP) as the module uses your local SimpleSAMLphp SP for the SAML + support. For more information on installing and configuring SimpleSAMLphp as + an SP visit: http://www.simplesamlphp.org. + + IMPORTANT: Your SP must be configured to use something other than phpsession + for session storage (in config/config.php set store.type => 'memcache' or 'sql'). + + To use memcache session handling you must have memcached installed on your + server and PHP must have the memcache extension. For more information on + installing the memcache extension for PHP visit: + http://www.php.net/manual/en/memcache.installation.php + + If you are on a shared host or a machine that you cannot install memcache on + then consider using the sql handler (store.type => 'sql'). + + +-- INSTALLATION -- + +Assuming the prerequisites have been met, installation of this module is just like any other Drupal module. + +1) Download the module +2) Uncompress it +3) Move it to the appropriate modules directory (usually, sites/all/modules) +4) Go to the Drupal module administration page for your site +5) Enable the module +6) Configure the module (see below) + + +-- CONFIGURATION -- + +The configuration of the module is fairly straight forward. You will need to +know the names of the attributes that your SP will be making available to the +module in order to map them into Drupal. + + +-- TROUBLESHOOTING -- + +The most common reason for things not working is the SP session storage type +is still set to phpsession. + + +-- CONTACT -- + +Current Maintainers +* Steve Moitozo (geekwisdom) http://drupal.org/user/1662 diff --git a/drupal/simplesamlphp_auth/simplesamlphp/config/authsources.php b/drupal/simplesamlphp_auth/simplesamlphp/config/authsources.php new file mode 100644 index 0000000..636b47b --- /dev/null +++ b/drupal/simplesamlphp_auth/simplesamlphp/config/authsources.php @@ -0,0 +1,334 @@ + array( + // The default is to use core:AdminPassword, but it can be replaced with + // any authentication source. + + 'core:AdminPassword', + ), + + + // An authentication source which can authenticate against both SAML 2.0 + // and Shibboleth 1.3 IdPs. + 'default-sp' => array( + 'saml:SP', + + // The entity ID of this SP. + // Can be NULL/unset, in which case an entity ID is generated based on the metadata URL. + 'entityID' => NULL, + + // The entity ID of the IdP this should SP should contact. + // Can be NULL/unset, in which case the user will be shown a list of available IdPs. + 'idp' => 'http://idp-montpellier.entrouvert.org/idp/saml2/metadata', + + // The URL to the discovery service. + // Can be NULL/unset, in which case a builtin discovery service will be used. + 'discoURL' => NULL, + + 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', + + ), + + + /* + 'example-sql' => array( + 'sqlauth:SQL', + 'dsn' => 'pgsql:host=sql.example.org;port=5432;dbname=simplesaml', + 'username' => 'simplesaml', + 'password' => 'secretpassword', + 'query' => 'SELECT "username", "name", "email" FROM "users" WHERE "username" = :username AND "password" = :password', + ), + */ + + /* + 'example-static' => array( + 'exampleauth:Static', + 'uid' => array('testuser'), + 'eduPersonAffiliation' => array('member', 'employee'), + 'cn' => array('Test User'), + ), + */ + + /* + 'example-userpass' => array( + 'exampleauth:UserPass', + 'student:studentpass' => array( + 'uid' => array('test'), + 'eduPersonAffiliation' => array('member', 'student'), + ), + 'employee:employeepass' => array( + 'uid' => array('employee'), + 'eduPersonAffiliation' => array('member', 'employee'), + ), + ), + */ + + /* + 'crypto-hash' => array( + 'authcrypt:Hash', + // hashed version of 'verysecret', made with bin/pwgen.php + 'professor:{SSHA256}P6FDTEEIY2EnER9a6P2GwHhI5JDrwBgjQ913oVQjBngmCtrNBUMowA==' => array( + 'uid' => array('prof_a'), + 'eduPersonAffiliation' => array('member', 'employee', 'board'), + ), + ), + */ + + /* + 'htpasswd' => array( + 'authcrypt:Htpasswd', + 'htpasswd_file' => '/var/www/foo.edu/legacy_app/.htpasswd', + 'static_attributes' => array( + 'eduPersonAffiliation' => array('member', 'employee'), + 'Organization' => array('University of Foo'), + ), + ), + */ + + /* + // This authentication source serves as an example of integration with an + // external authentication engine. Take a look at the comment in the beginning + // of modules/exampleauth/lib/Auth/Source/External.php for a description of + // how to adjust it to your own site. + 'example-external' => array( + 'exampleauth:External', + ), + */ + + /* + 'yubikey' => array( + 'authYubiKey:YubiKey', + 'id' => '000', + // 'key' => '012345678', + ), + */ + + /* + 'openid' => array( + 'openid:OpenIDConsumer', + 'attributes.required' => array('nickname'), + 'attributes.optional' => array('fullname', 'email',), + // 'sreg.validate' => FALSE, + 'attributes.ax_required' => array('http://axschema.org/namePerson/friendly'), + 'attributes.ax_optional' => array('http://axschema.org/namePerson','http://axschema.org/contact/email'), + // Prefer HTTP redirect over POST + // 'prefer_http_redirect' => FALSE, + ), + */ + + /* + // Example of an authsource that authenticates against Google. + // See: http://code.google.com/apis/accounts/docs/OpenID.html + 'google' => array( + 'openid:OpenIDConsumer', + // Googles OpenID endpoint. + 'target' => 'https://www.google.com/accounts/o8/id', + // Custom realm + // 'realm' => 'http://*.example.org', + // Attributes that google can supply. + 'attributes.ax_required' => array( + //'http://axschema.org/namePerson/first', + //'http://axschema.org/namePerson/last', + //'http://axschema.org/contact/email', + //'http://axschema.org/contact/country/home', + //'http://axschema.org/pref/language', + ), + // custom extension arguments + 'extension.args' => array( + //'http://specs.openid.net/extensions/ui/1.0' => array( + // 'mode' => 'popup', + // 'icon' => 'true', + //), + ), + ), + */ + + /* + 'papi' => array( + 'authpapi:PAPI', + ), + */ + + + /* + 'facebook' => array( + 'authfacebook:Facebook', + // Register your Facebook application on http://www.facebook.com/developers + // App ID or API key (requests with App ID should be faster; https://github.com/facebook/php-sdk/issues/214) + 'api_key' => 'xxxxxxxxxxxxxxxx', + // App Secret + 'secret' => 'xxxxxxxxxxxxxxxx', + // which additional data permissions to request from user + // see http://developers.facebook.com/docs/authentication/permissions/ for the full list + // 'req_perms' => 'email,user_birthday', + ), + */ + + /* + // LinkedIn OAuth Authentication API. + // Register your application to get an API key here: + // https://www.linkedin.com/secure/developer + 'linkedin' => array( + 'authlinkedin:LinkedIn', + 'key' => 'xxxxxxxxxxxxxxxx', + 'secret' => 'xxxxxxxxxxxxxxxx', + ), + */ + + /* + // Twitter OAuth Authentication API. + // Register your application to get an API key here: + // http://twitter.com/oauth_clients + 'twitter' => array( + 'authtwitter:Twitter', + 'key' => 'xxxxxxxxxxxxxxxx', + 'secret' => 'xxxxxxxxxxxxxxxx', + ), + */ + + /* + // MySpace OAuth Authentication API. + // Register your application to get an API key here: + // http://developer.myspace.com/ + 'myspace' => array( + 'authmyspace:MySpace', + 'key' => 'xxxxxxxxxxxxxxxx', + 'secret' => 'xxxxxxxxxxxxxxxx', + ), + */ + + /* + // Windows Live ID Authentication API. + // Register your application to get an API key here: + // https://manage.dev.live.com + 'windowslive' => array( + 'authwindowslive:LiveID', + 'key' => 'xxxxxxxxxxxxxxxx', + 'secret' => 'xxxxxxxxxxxxxxxx', + ), + */ + + /* + // Example of a LDAP authentication source. + 'example-ldap' => array( + 'ldap:LDAP', + + // The hostname of the LDAP server. + 'hostname' => 'ldap.example.org', + + // Whether SSL/TLS should be used when contacting the LDAP server. + 'enable_tls' => FALSE, + + // Whether debug output from the LDAP library should be enabled. + // Default is FALSE. + 'debug' => FALSE, + + // The timeout for accessing the LDAP server, in seconds. + // The default is 0, which means no timeout. + 'timeout' => 0, + + // Which attributes should be retrieved from the LDAP server. + // This can be an array of attribute names, or NULL, in which case + // all attributes are fetched. + 'attributes' => NULL, + + // The pattern which should be used to create the users DN given the username. + // %username% in this pattern will be replaced with the users username. + // + // This option is not used if the search.enable option is set to TRUE. + 'dnpattern' => 'uid=%username%,ou=people,dc=example,dc=org', + + // As an alternative to specifying a pattern for the users DN, it is possible to + // search for the username in a set of attributes. This is enabled by this option. + 'search.enable' => FALSE, + + // The DN which will be used as a base for the search. + // This can be a single string, in which case only that DN is searched, or an + // array of strings, in which case they will be searched in the order given. + 'search.base' => 'ou=people,dc=example,dc=org', + + // The attribute(s) the username should match against. + // + // This is an array with one or more attribute names. Any of the attributes in + // the array may match the value the username. + 'search.attributes' => array('uid', 'mail'), + + // The username & password the simpleSAMLphp should bind to before searching. If + // this is left as NULL, no bind will be performed before searching. + 'search.username' => NULL, + 'search.password' => NULL, + + // If the directory uses privilege separation, + // the authenticated user may not be able to retrieve + // all required attribures, a privileged entity is required + // to get them. This is enabled with this option. + 'priv.read' => FALSE, + + // The DN & password the simpleSAMLphp should bind to before + // retrieving attributes. These options are required if + // 'priv.read' is set to TRUE. + 'priv.username' => NULL, + 'priv.password' => NULL, + + ), + */ + + /* + // Example of an LDAPMulti authentication source. + 'example-ldapmulti' => array( + 'ldap:LDAPMulti', + + // The way the organization as part of the username should be handled. + // Three possible values: + // - 'none': No handling of the organization. Allows '@' to be part + // of the username. + // - 'allow': Will allow users to type 'username@organization'. + // - 'force': Force users to type 'username@organization'. The dropdown + // list will be hidden. + // + // The default is 'none'. + 'username_organization_method' => 'none', + + // Whether the organization should be included as part of the username + // when authenticating. If this is set to TRUE, the username will be on + // the form @. If this is FALSE, the + // username will be used as the user enters it. + // + // The default is FALSE. + 'include_organization_in_username' => FALSE, + + // A list of available LDAP servers. + // + // The index is an identifier for the organization/group. When + // 'username_organization_method' is set to something other than 'none', + // the organization-part of the username is matched against the index. + // + // The value of each element is an array in the same format as an LDAP + // authentication source. + 'employees' => array( + // A short name/description for this group. Will be shown in a dropdown list + // when the user logs on. + // + // This option can be a string or an array with language => text mappings. + 'description' => 'Employees', + + // The rest of the options are the same as those available for + // the LDAP authentication source. + 'hostname' => 'ldap.employees.example.org', + 'dnpattern' => 'uid=%username%,ou=employees,dc=example,dc=org', + ), + + 'students' => array( + 'description' => 'Students', + + 'hostname' => 'ldap.students.example.org', + 'dnpattern' => 'uid=%username%,ou=students,dc=example,dc=org', + ), + + ), + */ + +); diff --git a/drupal/simplesamlphp_auth/simplesamlphp/config/config.php b/drupal/simplesamlphp_auth/simplesamlphp/config/config.php new file mode 100644 index 0000000..f52b495 --- /dev/null +++ b/drupal/simplesamlphp_auth/simplesamlphp/config/config.php @@ -0,0 +1,650 @@ + 'attributemap/', + 'baseurlpath' => 'simplesamlphp/', + 'certdir' => 'cert/', + 'loggingdir' => 'log/', + 'datadir' => 'data/', + + + + + /* + * A directory where simpleSAMLphp can save temporary files. + * + * SimpleSAMLphp will attempt to create this directory if it doesn't exist. + */ + 'tempdir' => '/tmp/simplesaml', + + + /* + * If you enable this option, simpleSAMLphp will log all sent and received messages + * to the log file. + * + * This option also enables logging of the messages that are encrypted and decrypted. + * + * Note: The messages are logged with the DEBUG log level, so you also need to set + * the 'logging.level' option to LOG_DEBUG. + */ + 'debug' => FALSE, + + + 'showerrors' => TRUE, + + /** + * Custom error show function called from SimpleSAML_Error_Error::show. + * See docs/simplesamlphp-errorhandling.txt for function code example. + * + * Example: + * 'errors.show_function' => array('sspmod_example_Error_Show', 'show'), + */ + + /** + * This option allows you to enable validation of XML data against its + * schemas. A warning will be written to the log if validation fails. + */ + 'debug.validatexml' => FALSE, + + /** + * This password must be kept secret, and modified from the default value 123. + * This password will give access to the installation page of simpleSAMLphp with + * metadata listing and diagnostics pages. + * You can also put a hash here; run "bin/pwgen.php" to generate one. + */ + // Debian: this password is in /var/lib/simplesamlphp/secrets.inc.php + //'auth.adminpassword' => '123', + 'admin.protectindexpage' => false, + 'admin.protectmetadata' => false, + + /** + * This is a secret salt used by simpleSAMLphp when it needs to generate a secure hash + * of a value. It must be changed from its default value to a secret value. The value of + * 'secretsalt' can be any valid string of any length. + * + * A possible way to generate a random salt is by running the following command from a unix shell: + * tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' /dev/null;echo + */ + // Debian: this secret is in /var/lib/simplesamlphp/secrets.inc.php + //'secretsalt' => 'defaultsecretsalt', + + /* + * Some information about the technical persons running this installation. + * The email address will be used as the recipient address for error reports, and + * also as the technical contact in generated metadata. + */ + 'technicalcontact_name' => 'Administrator', + 'technicalcontact_email' => 'na@example.org', + + /* + * The timezone of the server. This option should be set to the timezone you want + * simpleSAMLphp to report the time in. The default is to guess the timezone based + * on your system timezone. + * + * See this page for a list of valid timezones: http://php.net/manual/en/timezones.php + */ + 'timezone' => NULL, + + /* + * Logging. + * + * define the minimum log level to log + * SimpleSAML_Logger::ERR No statistics, only errors + * SimpleSAML_Logger::WARNING No statistics, only warnings/errors + * SimpleSAML_Logger::NOTICE Statistics and errors + * SimpleSAML_Logger::INFO Verbose logs + * SimpleSAML_Logger::DEBUG Full debug logs - not reccomended for production + * + * Choose logging handler. + * + * Options: [syslog,file,errorlog] + * + */ + 'logging.level' => SimpleSAML_Logger::NOTICE, + 'logging.handler' => 'syslog', + + /* + * Choose which facility should be used when logging with syslog. + * + * These can be used for filtering the syslog output from simpleSAMLphp into its + * own file by configuring the syslog daemon. + * + * See the documentation for openlog (http://php.net/manual/en/function.openlog.php) for available + * facilities. Note that only LOG_USER is valid on windows. + * + * The default is to use LOG_LOCAL5 if available, and fall back to LOG_USER if not. + */ + 'logging.facility' => defined('LOG_LOCAL5') ? constant('LOG_LOCAL5') : LOG_USER, + + /* + * The process name that should be used when logging to syslog. + * The value is also written out by the other logging handlers. + */ + 'logging.processname' => 'simplesamlphp', + + /* Logging: file - Logfilename in the loggingdir from above. + */ + 'logging.logfile' => 'simplesamlphp.log', + + /* (New) statistics output configuration. + * + * This is an array of outputs. Each output has at least a 'class' option, which + * selects the output. + */ + 'statistics.out' => array( + // Log statistics to the normal log. + /* + array( + 'class' => 'core:Log', + 'level' => 'notice', + ), + */ + // Log statistics to files in a directory. One file per day. + /* + array( + 'class' => 'core:File', + 'directory' => '/var/log/stats', + ), + */ + ), + + + /* + * Enable + * + * Which functionality in simpleSAMLphp do you want to enable. Normally you would enable only + * one of the functionalities below, but in some cases you could run multiple functionalities. + * In example when you are setting up a federation bridge. + */ + 'enable.saml20-idp' => false, + 'enable.shib13-idp' => false, + 'enable.adfs-idp' => false, + 'enable.wsfed-sp' => false, + 'enable.authmemcookie' => false, + + /* + * This value is the duration of the session in seconds. Make sure that the time duration of + * cookies both at the SP and the IdP exceeds this duration. + */ + 'session.duration' => 8 * (60*60), // 8 hours. + 'session.requestcache' => 4 * (60*60), // 4 hours + + /* + * Sets the duration, in seconds, data should be stored in the datastore. As the datastore is used for + * login and logout requests, thid option will control the maximum time these operations can take. + * The default is 4 hours (4*60*60) seconds, which should be more than enough for these operations. + */ + 'session.datastore.timeout' => (4*60*60), // 4 hours + + /* + * Sets the duration, in seconds, auth state should be stored. + */ + 'session.state.timeout' => (60*60), // 1 hour + + /* + * Option to override the default settings for the session cookie name + */ + 'session.cookie.name' => 'SimpleSAMLSessionID', + + /* + * Expiration time for the session cookie, in seconds. + * + * Defaults to 0, which means that the cookie expires when the browser is closed. + * + * Example: + * 'session.cookie.lifetime' => 30*60, + */ + 'session.cookie.lifetime' => 0, + + /* + * Limit the path of the cookies. + * + * Can be used to limit the path of the cookies to a specific subdirectory. + * + * Example: + * 'session.cookie.path' => '/simplesaml/', + */ + 'session.cookie.path' => '/', + + /* + * Cookie domain. + * + * Can be used to make the session cookie available to several domains. + * + * Example: + * 'session.cookie.domain' => '.example.org', + */ + 'session.cookie.domain' => NULL, + + /* + * Set the secure flag in the cookie. + * + * Set this to TRUE if the user only accesses your service + * through https. If the user can access the service through + * both http and https, this must be set to FALSE. + */ + 'session.cookie.secure' => FALSE, + + /* + * When set to FALSE fallback to transient session on session initialization + * failure, throw exception otherwise. + */ + 'session.disable_fallback' => FALSE, + + /* + * Enable secure POST from HTTPS to HTTP. + * + * If you have some SP's on HTTP and IdP is normally on HTTPS, this option + * enables secure POSTing to HTTP endpoint without warning from browser. + * + * For this to work, module.php/core/postredirect.php must be accessible + * also via HTTP on IdP, e.g. if your IdP is on + * https://idp.example.org/ssp/, then + * http://idp.example.org/ssp/module.php/core/postredirect.php must be accessible. + */ + 'enable.http_post' => FALSE, + + /* + * Options to override the default settings for php sessions. + */ + 'session.phpsession.cookiename' => null, + 'session.phpsession.savepath' => null, + 'session.phpsession.httponly' => FALSE, + + /* + * Option to override the default settings for the auth token cookie + */ + 'session.authtoken.cookiename' => 'SimpleSAMLAuthToken', + + /* + * Languages available, RTL languages, and what language is default + */ + 'language.available' => array('en', 'no', 'nn', 'se', 'da', 'de', 'sv', 'fi', 'es', 'fr', 'it', 'nl', 'lb', 'cs', 'sl', 'lt', 'hr', 'hu', 'pl', 'pt', 'pt-br', 'tr', 'ja', 'zh', 'zh-tw', 'ru', 'et', 'he', 'id'), + 'language.rtl' => array('ar','dv','fa','ur','he'), + 'language.default' => 'en', + + /** + * Custom getLanguage function called from SimpleSAML_XHTML_Template::getLanguage(). + * Function should return language code of one of the available languages or NULL. + * See SimpleSAML_XHTML_Template::getLanguage() source code for more info. + * + * This option can be used to implement a custom function for determining + * the default language for the user. + * + * Example: + * 'language.get_language_function' => array('sspmod_example_Template', 'getLanguage'), + */ + + /* + * Extra dictionary for attribute names. + * This can be used to define local attributes. + * + * The format of the parameter is a string with :. + * + * Specifying this option will cause us to look for modules//dictionaries/.definition.json + * The dictionary should look something like: + * + * { + * "firstattribute": { + * "en": "English name", + * "no": "Norwegian name" + * }, + * "secondattribute": { + * "en": "English name", + * "no": "Norwegian name" + * } + * } + * + * Note that all attribute names in the dictionary must in lowercase. + * + * Example: 'attributes.extradictionary' => 'ourmodule:ourattributes', + */ + 'attributes.extradictionary' => NULL, + + /* + * Which theme directory should be used? + */ + 'theme.use' => 'default', + + + /* + * Default IdP for WS-Fed. + */ + 'default-wsfed-idp' => 'urn:federation:pingfederate:localhost', + + /* + * Whether the discovery service should allow the user to save his choice of IdP. + */ + 'idpdisco.enableremember' => TRUE, + 'idpdisco.rememberchecked' => TRUE, + + // Disco service only accepts entities it knows. + 'idpdisco.validate' => TRUE, + + 'idpdisco.extDiscoveryStorage' => NULL, + + /* + * IdP Discovery service look configuration. + * Wether to display a list of idp or to display a dropdown box. For many IdP' a dropdown box + * gives the best use experience. + * + * When using dropdown box a cookie is used to highlight the previously chosen IdP in the dropdown. + * This makes it easier for the user to choose the IdP + * + * Options: [links,dropdown] + * + */ + 'idpdisco.layout' => 'dropdown', + + /* + * Whether simpleSAMLphp should sign the response or the assertion in SAML 1.1 authentication + * responses. + * + * The default is to sign the assertion element, but that can be overridden by setting this + * option to TRUE. It can also be overridden on a pr. SP basis by adding an option with the + * same name to the metadata of the SP. + */ + 'shib13.signresponse' => TRUE, + + + + /* + * Authentication processing filters that will be executed for all IdPs + * Both Shibboleth and SAML 2.0 + */ + 'authproc.idp' => array( + /* Enable the authproc filter below to add URN Prefixces to all attributes + 10 => array( + 'class' => 'core:AttributeMap', 'addurnprefix' + ), */ + /* Enable the authproc filter below to automatically generated eduPersonTargetedID. + 20 => 'core:TargetedID', + */ + + // Adopts language from attribute to use in UI + 30 => 'core:LanguageAdaptor', + + /* Add a realm attribute from edupersonprincipalname + 40 => 'core:AttributeRealm', + */ + 45 => array( + 'class' => 'core:StatisticsWithAttribute', + 'attributename' => 'realm', + 'type' => 'saml20-idp-SSO', + ), + + /* When called without parameters, it will fallback to filter attributes ‹the old way› + * by checking the 'attributes' parameter in metadata on IdP hosted and SP remote. + */ + 50 => 'core:AttributeLimit', + + /* + * Search attribute "distinguishedName" for pattern and replaces if found + + 60 => array( + 'class' => 'core:AttributeAlter', + 'pattern' => '/OU=studerende/', + 'replacement' => 'Student', + 'subject' => 'distinguishedName', + '%replace', + ), + */ + + /* + * Consent module is enabled (with no permanent storage, using cookies). + + 90 => array( + 'class' => 'consent:Consent', + 'store' => 'consent:Cookie', + 'focus' => 'yes', + 'checked' => TRUE + ), + */ + // If language is set in Consent module it will be added as an attribute. + 99 => 'core:LanguageAdaptor', + ), + /* + * Authentication processing filters that will be executed for all SPs + * Both Shibboleth and SAML 2.0 + */ + 'authproc.sp' => array( + /* + 10 => array( + 'class' => 'core:AttributeMap', 'removeurnprefix' + ), + */ + 10 => array( + 'class' => 'saml:NameIDAttribute', + 'format' => '%V', + 'attribute' => 'NameID', + ), + /* + * Generate the 'group' attribute populated from other variables, including eduPersonAffiliation. + */ + 60 => array('class' => 'core:GenerateGroups', 'eduPersonAffiliation'), + // All users will be members of 'users' and 'members' + //61 => array('class' => 'core:AttributeAdd', 'groups' => array('users', 'members')), + + // Adopts language from attribute to use in UI + 90 => 'core:LanguageAdaptor', + + ), + + + /* + * This option configures the metadata sources. The metadata sources is given as an array with + * different metadata sources. When searching for metadata, simpleSAMPphp will search through + * the array from start to end. + * + * Each element in the array is an associative array which configures the metadata source. + * The type of the metadata source is given by the 'type' element. For each type we have + * different configuration options. + * + * Flat file metadata handler: + * - 'type': This is always 'flatfile'. + * - 'directory': The directory we will load the metadata files from. The default value for + * this option is the value of the 'metadatadir' configuration option, or + * 'metadata/' if that option is unset. + * + * XML metadata handler: + * This metadata handler parses an XML file with either an EntityDescriptor element or an + * EntitiesDescriptor element. The XML file may be stored locally, or (for debugging) on a remote + * web server. + * The XML hetadata handler defines the following options: + * - 'type': This is always 'xml'. + * - 'file': Path to the XML file with the metadata. + * - 'url': The url to fetch metadata from. THIS IS ONLY FOR DEBUGGING - THERE IS NO CACHING OF THE RESPONSE. + * + * + * Examples: + * + * This example defines two flatfile sources. One is the default metadata directory, the other + * is a metadata directory with autogenerated metadata files. + * + * 'metadata.sources' => array( + * array('type' => 'flatfile'), + * array('type' => 'flatfile', 'directory' => 'metadata-generated'), + * ), + * + * This example defines a flatfile source and an XML source. + * 'metadata.sources' => array( + * array('type' => 'flatfile'), + * array('type' => 'xml', 'file' => 'idp.example.org-idpMeta.xml'), + * ), + * + * + * Default: + * 'metadata.sources' => array( + * array('type' => 'flatfile') + * ), + */ + 'metadata.sources' => array( + array('type' => 'flatfile'), + ), + + + /* + * Configure the datastore for simpleSAMLphp. + * + * - 'phpsession': Limited datastore, which uses the PHP session. + * - 'memcache': Key-value datastore, based on memcache. + * - 'sql': SQL datastore, using PDO. + * + * The default datastore is 'phpsession'. + * + * (This option replaces the old 'session.handler'-option.) + */ + 'store.type' => 'memcache', + + + /* + * The DSN the sql datastore should connect to. + * + * See http://www.php.net/manual/en/pdo.drivers.php for the various + * syntaxes. + */ + 'store.sql.dsn' => 'sqlite:/path/to/sqlitedatabase.sq3', + + /* + * The username and password to use when connecting to the database. + */ + 'store.sql.username' => NULL, + 'store.sql.password' => NULL, + + /* + * The prefix we should use on our tables. + */ + 'store.sql.prefix' => 'simpleSAMLphp', + + + /* + * Configuration for the MemcacheStore class. This allows you to store + * multiple redudant copies of sessions on different memcache servers. + * + * 'memcache_store.servers' is an array of server groups. Every data + * item will be mirrored in every server group. + * + * Each server group is an array of servers. The data items will be + * load-balanced between all servers in each server group. + * + * Each server is an array of parameters for the server. The following + * options are available: + * - 'hostname': This is the hostname or ip address where the + * memcache server runs. This is the only required option. + * - 'port': This is the port number of the memcache server. If this + * option isn't set, then we will use the 'memcache.default_port' + * ini setting. This is 11211 by default. + * - 'weight': This sets the weight of this server in this server + * group. http://php.net/manual/en/function.Memcache-addServer.php + * contains more information about the weight option. + * - 'timeout': The timeout for this server. By default, the timeout + * is 3 seconds. + * + * Example of redudant configuration with load balancing: + * This configuration makes it possible to lose both servers in the + * a-group or both servers in the b-group without losing any sessions. + * Note that sessions will be lost if one server is lost from both the + * a-group and the b-group. + * + * 'memcache_store.servers' => array( + * array( + * array('hostname' => 'mc_a1'), + * array('hostname' => 'mc_a2'), + * ), + * array( + * array('hostname' => 'mc_b1'), + * array('hostname' => 'mc_b2'), + * ), + * ), + * + * Example of simple configuration with only one memcache server, + * running on the same computer as the web server: + * Note that all sessions will be lost if the memcache server crashes. + * + * 'memcache_store.servers' => array( + * array( + * array('hostname' => 'localhost'), + * ), + * ), + * + */ + 'memcache_store.servers' => array( + array( + array('hostname' => 'localhost'), + ), + ), + + + /* + * This value is the duration data should be stored in memcache. Data + * will be dropped from the memcache servers when this time expires. + * The time will be reset every time the data is written to the + * memcache servers. + * + * This value should always be larger than the 'session.duration' + * option. Not doing this may result in the session being deleted from + * the memcache servers while it is still in use. + * + * Set this value to 0 if you don't want data to expire. + * + * Note: The oldest data will always be deleted if the memcache server + * runs out of storage space. + */ + 'memcache_store.expires' => 36 * (60*60), // 36 hours. + + + /* + * Should signing of generated metadata be enabled by default. + * + * Metadata signing can also be enabled for a individual SP or IdP by setting the + * same option in the metadata for the SP or IdP. + */ + 'metadata.sign.enable' => FALSE, + + /* + * The default key & certificate which should be used to sign generated metadata. These + * are files stored in the cert dir. + * These values can be overridden by the options with the same names in the SP or + * IdP metadata. + * + * If these aren't specified here or in the metadata for the SP or IdP, then + * the 'certificate' and 'privatekey' option in the metadata will be used. + * if those aren't set, signing of metadata will fail. + */ + 'metadata.sign.privatekey' => NULL, + 'metadata.sign.privatekey_pass' => NULL, + 'metadata.sign.certificate' => NULL, + + + /* + * Proxy to use for retrieving URLs. + * + * Example: + * 'proxy' => 'tcp://proxy.example.com:5100' + */ + 'proxy' => NULL, + +); + +require_once('/var/lib/simplesamlphp/secrets.inc.php'); diff --git a/drupal/simplesamlphp_auth/simplesamlphp/metadata/saml20-idp-remote.php b/drupal/simplesamlphp_auth/simplesamlphp/metadata/saml20-idp-remote.php new file mode 100644 index 0000000..4af9c72 --- /dev/null +++ b/drupal/simplesamlphp_auth/simplesamlphp/metadata/saml20-idp-remote.php @@ -0,0 +1,53 @@ + 'http://idp-montpellier.entrouvert.org/idp/saml2/metadata', + 'metadata-set' => 'saml20-idp-remote', + 'SingleSignOnService' => + array ( + 0 => + array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'http://idp-montpellier.entrouvert.org/idp/saml2/sso', + ), + 1 => + array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + 'Location' => 'http://idp-montpellier.entrouvert.org/idp/saml2/sso', + ), + ), + 'SingleLogoutService' => + array ( + 0 => + array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', + 'Location' => 'http://idp-montpellier.entrouvert.org/idp/saml2/slo', + 'ResponseLocation' => 'http://idp-montpellier.entrouvert.org/idp/saml2/slo_return', + ), + 1 => + array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + 'Location' => 'http://idp-montpellier.entrouvert.org/idp/saml2/slo', + 'ResponseLocation' => 'http://idp-montpellier.entrouvert.org/idp/saml2/slo_return', + ), + 2 => + array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP', + 'Location' => 'http://idp-montpellier.entrouvert.org/idp/saml2/slo/soap', + ), + ), + 'ArtifactResolutionService' => + array ( + 0 => + array ( + 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP', + 'Location' => 'http://idp-montpellier.entrouvert.org/idp/saml2/artifact', + 'index' => 1, + ), + ), + 'certFingerprint' => + array ( + 0 => 'f9af51c1613752e3ab4aa12f5b8f0fbfae7de6af', + ), + 'certData' => 'MIIDIzCCAgugAwIBAgIJANUBoick1pDpMA0GCSqGSIb3DQEBBQUAMBUxEzARBgNVBAoTCkVudHJvdXZlcnQwHhcNMTAxMjE0MTUzMzAyWhcNMTEwMTEzMTUzMzAyWjAVMRMwEQYDVQQKEwpFbnRyb3V2ZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvxFkfPdndlGgQPDZgFGXbrNAc/79PULZBuNdWFHDD9P5hNhZn9Kqm4Cp06Pe/A6u+g5wLnYvbZQcFCgfQAEzziJtb3J55OOlB7iMEI/T2AX2WzrUH8QT8NGhABONKU2Gg4XiyeXNhH5R7zdHlUwcWq3ZwNbtbY0TVc+n665EbrfV/59xihSqsoFrkmBLH0CoepUXtAzA7WDYn8AzusIuMx3n8844pJwgxhTB7Gjuboptlz9Hri8JRdXiVT9OS9Wt69ubcNoM6zuKASmtm48UuGnhj8v6XwvbjKZrL9kA+xf8ziazZfvvw/VGTm+IVFYB7d1x457jY5zjjXJvNysoowIDAQABo3YwdDAdBgNVHQ4EFgQUeF8ePnu0fcAK50iBQDgAhHkOu8kwRQYDVR0jBD4wPIAUeF8ePnu0fcAK50iBQDgAhHkOu8mhGaQXMBUxEzARBgNVBAoTCkVudHJvdXZlcnSCCQDVAaInJNaQ6TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAy8l3GhUtpPHx0FxzbRHVaaUSgMwYKGPhEIdGhqekKUJIx8et4xpEMFBl5XQjBNq/mp5vO3SPb2h2PVSks7xWnG3cvEkqJSOeofEEhkqnM45b2MH1S5uxp4i8UilPG6kmQiXU2rEUBdRk9xnRWos7epVivTSIv1NcplG6l41SXp6YgIb2ToT+rOKdIGIQuGDlzeR88fDxWEU0vEujZv/v1PE1YOV0xKjTTJumlBc6IViKhJeo1wiBBrVRIIkKKevHKQzteK8pWm9CYWculxT26TZ4VWzGbo06jo2zbumirrLLqnt1gmBDvDvlOwC/zAAyL4chbz66eQHTiIYZZvYgy', +); + diff --git a/drupal/simplesamlphp_auth/simplesamlphp_auth.info b/drupal/simplesamlphp_auth/simplesamlphp_auth.info new file mode 100644 index 0000000..b755b8d --- /dev/null +++ b/drupal/simplesamlphp_auth/simplesamlphp_auth.info @@ -0,0 +1,12 @@ +name = simpleSAMLphp authentication +description = Allows users to authenticate to a remote SAML identity provider (IdP) via a locally configured SimpleSAMLphp service point (SP). +php = 5.1 +core = 7.x +configure = admin/config/people/simplesamlphp_auth + +; Information added by drupal.org packaging script on 2013-02-11 +version = "7.x-2.0-alpha2" +core = "7.x" +project = "simplesamlphp_auth" +datestamp = "1360609258" + diff --git a/drupal/simplesamlphp_auth/simplesamlphp_auth.install b/drupal/simplesamlphp_auth/simplesamlphp_auth.install new file mode 100644 index 0000000..9174767 --- /dev/null +++ b/drupal/simplesamlphp_auth/simplesamlphp_auth.install @@ -0,0 +1,49 @@ + 'SimpleSAMLphp Auth Settings', + 'description' => 'Control the various settings of the simpleSAMLphp authentication module', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('simplesamlphp_auth_settings'), + 'access arguments' => array('administer simpleSAMLphp authentication'), + 'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM, + ); + $items['saml_login'] = array( + 'title' => 'Logon to the site', + 'description' => 'Provides a site login page', + 'page callback' => 'simplesamlphp_auth_loginpage', + 'access callback' => TRUE, + 'type' => MENU_CALLBACK, + ); + + return $items; +} + +/** + * Implements hook_admin_paths(). + */ +function simplesamlphp_auth_admin_paths() { + return array('admin/config/people/simplesamlphp_auth' => TRUE); +} + +/** + * Implements hook_help(). + */ +function simplesamlphp_auth_help($path, $arg) { + switch ($path) { + case 'admin/config/people/simplesamlphp_auth': + $output = t('

This module integrates Drupal with a SimpleSAMLphp Service Point (SP), effectively federating Drupal.

'); + $output .= t('

'); + return $output; + } +} + +/** + * Implements hook_permission(). + */ +function simplesamlphp_auth_permission() { + return array( + 'administer simpleSAMLphp authentication' => array( + 'title' => t('Administer simpleSAMLphp authentication'), + 'description' => t('Warning: Give to trusted roles only; this permission has security implications.'), + ), + ); +} + + +/** + * Represents the Drupal page (saml_login), which triggers user authentication against the SimpleSAMLphp service provider. + */ +function simplesamlphp_auth_loginpage() { + global $user; + global $base_url; + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + + $fail = NULL; + $output = NULL; + + if (!_simplesamlphp_auth_isEnabled()) { + // Exit without initializing. + drupal_set_message(t('We\'re sorry this feature is not yet enabled.')); + return ''; + } + + // Do some sanity checking before attempting anything. + $config = SimpleSAML_Configuration::getInstance(); + $configStoreType = $config->getValue('store.type'); + + // Make sure phpsession is NOT being used. + if ($configStoreType == 'phpsession') { + watchdog('simplesamlphp_auth', 'A user attempted to login using simplesamlphp but the store.type is phpsession, use memcache or sql for simplesamlphp session storage. See: simplesamlphp/config/config.php.', NULL, WATCHDOG_WARNING); + $fail = TRUE; + } + + // Make sure there is an instance of SimpleSAML_Auth_Simple. + if (!$_simplesamlphp_auth_as) { + watchdog('simplesamlphp_auth', 'A user attempted to login using this module but there was a problem.', NULL, WATCHDOG_WARNING); + $fail = TRUE; + } + + // There was a problem, we can't go on, but we don't want to tell the user any specifics either. + if ($fail) { + drupal_set_message(t('We\'re sorry. There was a problem. The issue has been logged for the administrator.')); + drupal_goto(base_path()); + } + + $returnto = NULL; + + // Support for deep linking. + + // See if a URL has been explicitly provided in ReturnTo. If so, use it (as long as it points to this site). + if ((isset($_REQUEST['ReturnTo']) && $_REQUEST['ReturnTo']) && + (valid_url($_REQUEST['ReturnTo']) && stristr($_REQUEST['ReturnTo'], $base_url))) { + + $returnto = $_REQUEST['ReturnTo']; + + // If not, see if a REFERER URL is available. If so, use it (as long as it points to this site). + } + elseif ((isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER']) && + (valid_url($_SERVER['HTTP_REFERER']) && stristr($_SERVER['HTTP_REFERER'], $base_url))) { + + $returnto = $_SERVER['HTTP_REFERER']; + } + + // If the user is anonymous, set the cookie (if we can) and require authentication. + if ($user->uid == 0) { + + if ($returnto) { + // Set the cookie so we can deliver the user to the place they started + setrawcookie('simplesamlphp_auth_returnto', $returnto, time()+60*60); + } + + // Require the user to be authenticated. + $_simplesamlphp_auth_as->requireAuth(); + + + // If the user is authenticated, send them along. + } + else { + + $gotourl = NULL; + + // Check to see if we've set a cookie. If there is one, give it priority. + if (isset($_COOKIE['simplesamlphp_auth_returnto']) && $_COOKIE['simplesamlphp_auth_returnto']) { + // use the cookie for the ReturnTo + $gotourl = $_COOKIE['simplesamlphp_auth_returnto']; + + // unset the cookie + setrawcookie('simplesamlphp_auth_returnto', ''); + + } + elseif ($returnto) { + $gotourl = $returnto; + } + + + // If a ReturnTo has been set. + if ($gotourl) { + drupal_goto(str_replace($base_url . '/', '', $gotourl)); + } + else { + drupal_goto('user/' . $user->uid); + } + + } + + return drupal_goto(base_path()); +} + +/** + * Implements hook_init(). + */ +function simplesamlphp_auth_init() { + global $user; + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + global $_simplesamlphp_auth_saml_config; + global $_simplesamlphp_auth_saml_version; + + if (!_simplesamlphp_auth_isEnabled(TRUE)) { + // Exit without initializing. + return; + } + + // Get the simplesamlphp session. + $basedir = variable_get('simplesamlphp_auth_installdir', 'sites/all/modules/simplesamlphp_auth/simplesamlphp'); + + require_once($basedir . '/lib/_autoload.php'); + + $_simplesamlphp_auth_saml_config = SimpleSAML_Configuration::getInstance(); + $_simplesamlphp_auth_saml_version = $_simplesamlphp_auth_saml_config->getVersion(); + + // Load simpleSAMLphp, configuration and metadata. + $_simplesamlphp_auth_as = new SimpleSAML_Auth_Simple(variable_get('simplesamlphp_auth_authsource', 'default-sp')); + $_simplesamlphp_auth_saml_attributes = $_simplesamlphp_auth_as->getAttributes(); + + if ($user->uid == 0) { + // User is not logged in to Drupal. + if ($_simplesamlphp_auth_as->isAuthenticated()) { + // User is logged in - SimpleSAMLphp (but not Drupal). + $authname = _simplesamlphp_auth_get_authname(); + try { + $name = _simplesamlphp_auth_get_default_name(); + _simplesaml_auth_debug(t('Registering user [%acctname]', array('%acctname' => $name))); + } + catch (Exception $e) { + drupal_set_message(t("Impossible de fédérer votre compte : nom d'utilisateur non envoyé."), "error"); + watchdog('simplesamlphp_auth', $e->getMessage(), NULL, WATCHDOG_CRITICAL); + return; + } + _simplesaml_auth_debug(t('Authname is [%authname] userid is [%uid]', array('%authname' => $authname, '%uid' => $user->uid))); + + if (!empty($authname)) { + // User is logged in with SAML authentication and we got the unique identifier. + // Try to log into Drupal. + _simplesaml_auth_debug(t('Load user [%authname]', array('%authname' => $authname))); + + // Retrieve user mapping and attempt to log the user in. + // @todo : add authmapper here + $ext_user = user_external_load($authname); + + + if (!$ext_user) { + // First we check the admin settings for simpleSAMLphp and find out if we are allowed to register users. + if (variable_get('simplesamlphp_auth_registerusers', TRUE)) { + + // We are allowed to register new users. + _simplesaml_auth_debug(t('Register [%authname]', array('%authname' => $authname))); + + user_external_login_register($authname, 'simplesamlphp_auth'); + + if ($user) { + // Populate roles based on configuration setting. + $roles = _simplesamlphp_auth_rolepopulation(variable_get('simplesamlphp_auth_rolepopulation', '')); + $userinfo = array('roles' => $roles); + $user = user_save($user, $userinfo); // @todo - Fjernet rolle-delen her da den gav en bra feilmelding når roller ikke finnes ;) + } + + } + else { + // We are not allowed to register new users on the site through simpleSAML. + // We let the user know about this and redirect to the user/login page. + $msg = t("We are sorry. While you have successfully authenticated, you are not yet entitled to access this site. Please ask the site administrator to provision access for you."); + drupal_set_message(check_plain($msg)); + $_simplesamlphp_auth_as->logout(base_path()); + } + } + else { + // If successfully logged into Drupal. + // See if we're supposed to re-evaluate role assignments. + + if (variable_get('simplesamlphp_auth_roleevaleverytime', 0)) { + // If the user is already registered... + // Update the roles. + // Populate roles based on configuration setting. + _simplesaml_auth_debug(t('User already registered [%authname] updating roles.', array('%authname' => $authname))); + $roles = _simplesamlphp_auth_rolepopulation(variable_get('simplesamlphp_auth_rolepopulation', '')); + $userinfo = array('roles' => $roles); + + // Save the updated roles and populate the user object. + $user = user_save($ext_user, $userinfo); + } + else { + // No need to evaluate roles, populate the user object. + $user = $ext_user; + } + + if (module_exists('rules')) { + rules_invoke_event('simplesamlphp_auth_rules_event_login', $user); + } + + } + + // Finalizing the login, calls hook_user op login. + $edit = array(); + user_login_finalize($edit); + + } // End if !empty authname. + } // End if isset saml_session. + } + else { + // The user is already logged into Drupal. + // If we forbid users from logging in using local accounts. + if (FALSE == variable_get('simplesamlphp_auth_allowdefaultlogin', TRUE)) { + // If the user has NOT been authenticated via simpleSAML... + if (!$_simplesamlphp_auth_as->isAuthenticated()) { + // :FYI: Until Drupal issue #754560 is corrected this message will never be seen by the user. + drupal_set_message(t("We are sorry, users are not permitted to log in using local accounts.")); + // Destroy the user's session (log them out). + _simplesamlphp_auth_destroy_drupal_session(); + } + } + else { + // If we are allowing users to log in with local accounts. + // If the user has NOT been authenticated via simpleSAML. + if (!$_simplesamlphp_auth_as->isAuthenticated()) { + + // See if we limit this privilege to specified users + $strAllwDefLogUsers = variable_get('simplesamlphp_auth_allowdefaultloginusers', ''); + $arrAllwDefLogUsers = array(); + // See if we limit this privilege to specified roles. + $arrAllwDefLogRoles = variable_get('simplesamlphp_auth_allowdefaultloginroles', FALSE); + + // If user IDs or roles are specified, we let them in, but everyone else gets logged out. + if (drupal_strlen($strAllwDefLogUsers) || $arrAllwDefLogRoles) { + + // Convert the string into an array. + // @todo Perform a test to make sure that only numbers, spaces, or commas are in the string. + $arrAllwDefLogUsers = explode(',', $strAllwDefLogUsers); + + // If we still have something to work with. + if (0 < count($arrAllwDefLogUsers) || 0 < count($arrAllwDefLogRoles)) { + /* Log the user out of Drupal if: + 1) the current user's uid is NOT in the list of allowed uids... + 2) or their role does not match and allowed mixed mode role. */ + $matchRoles = array_intersect(array_keys($user->roles), $arrAllwDefLogRoles); + if (!in_array($user->uid, $arrAllwDefLogUsers) && count($matchRoles) == 0) { + // User is logged into Drupal, but may not be logged into simpleSAML. + // If this is the case we're supposed to log the user out of Drupal. + + // :FYI: Until Drupal issue #754560 is corrected this message will never be seen by the user. + drupal_set_message(t("We are sorry, you are not permitted to log in using a local account.")); + + // The least we can do is write something to the watchdog so someone will know what's happening. + watchdog('simplesamlphp_auth', 'User %name not authorized to log in using local account.', array('%name' => $user->name)); + + _simplesamlphp_auth_destroy_drupal_session(); + } + } + + } // Test for specified users. + + } // End if $_simplesamlphp_auth_as->isAuthenticated(). + } // End test to see if we allow default logins. + } // End if user->uid. + simplesamlphp_sync_attributes(); +} + +/* Implement hook_auth_user_insert() */ +function simplesamlphp_auth_user_insert(&$edit, $account, $category = NUL) { + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + + if (!_simplesamlphp_auth_isEnabled()) { + // Exit without initializing. + return; + } + if ($category = 'account') { + if ($_simplesamlphp_auth_as->isAuthenticated()) { + $name = ''; + try { + $name = _simplesamlphp_auth_get_default_name(); + _simplesaml_auth_debug(t('Registering user [%acctname]', array('%acctname' => $name))); + } + catch (Exception $e) { + drupal_set_message(t("Nom d'utilisateur non disponnible."), "error"); + watchdog('simplesamlphp_auth', $e->getMessage(), NULL, WATCHDOG_CRITICAL); + } + if (!$name) + $name='inconnu'; + $origin_name = $name; + $i = 0; + while (db_select('users', 'u')->fields('u')->condition('name', $name, '=')->execute()->fetchAssoc()) { + $name = $origin_name . "$i"; + $i++; + } + db_update('users') + ->fields(array('name' => $name)) + ->condition('uid', $account->uid) + ->execute(); + + } + if (module_exists('rules')) { + rules_invoke_event('simplesamlphp_auth_rules_event_register', $account); + } + } +} + +/** + * Sync attributes + */ +function simplesamlphp_sync_attributes() { + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + global $user; + + if (!_simplesamlphp_auth_isEnabled() or !$user) { + // Exit without initializing. + return; + } + + // If user registration has a valid session... + if ($_simplesamlphp_auth_as->isAuthenticated()) { + $user = user_load($user->uid); + // Get name from default attributes. + + _simplesaml_auth_debug(t('Updating username [%acctname]', array('%acctname' => $user->name))); + + // Get mail from default attribute. + try { + $mail_address = _simplesamlphp_auth_get_attr('simplesamlphp_auth_mailattr', 'email'); + $first_name = _simplesamlphp_auth_get_attr('simplesamlphp_auth_first_name', 'gn'); + } + catch (Exception $e) { + drupal_set_message(t('Prénom ou email non disponnible.'), "error"); + watchdog('simplesamlphp_auth', $e->getMessage(), NULL, WATCHDOG_CRITICAL); + } + + $data = array('nameid' => _simplesamlphp_auth_get_authname()); + $fields = array('data' => $data); + if (!empty($mail_address)) + $fields["mail"] = $mail_address; + if (!empty($first_name)) + { + $fields['field_prenom'] = array( + 'und' => array( + 0 => array('value' => $first_name), + ), + ); + } + + $prenom = field_get_items('user', $user, 'field_prenom'); + user_save($user, $fields); + + + //_simplesaml_auth_debug(t('Updating mail [%mailaddr]', array('%mailaddr' => $mail_address))); + } +} + +/** + * Implements hook_user_logout(). + */ +function simplesamlphp_auth_user_logout($account) { + global $user; + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + global $base_url; + + if (!empty($_simplesamlphp_auth_saml_attributes)) { + + $config = SimpleSAML_Configuration::getInstance(); + + // :KLUDGE: for some reason Drupal is not killing the session, even if I were to call drupal_session_destroy_uid() here. + session_destroy(); + + $gotourl = base_path(); + if (variable_get('simplesamlphp_auth_logoutgotourl', '')) { + $gotourl = variable_get('simplesamlphp_auth_logoutgotourl', ''); + } + + $_simplesamlphp_auth_as->logout($gotourl); + + } +} + +/** + * Implements hook_user_delete(). + */ +/*function simplesamlphp_auth_user_delete($account) { + db_delete('authmap') + ->condition('uid', $account->uid) + ->condition('name', $account->name) + ->execute(); +}*/ + +/** + * Implements settings for the module. + */ +function simplesamlphp_auth_settings() { + global $_simplesamlphp_auth_saml_version, $base_url; + + if (!empty($_simplesamlphp_auth_saml_version )) { + $ver = explode('.', $_simplesamlphp_auth_saml_version); + if ( !($ver[0] >= 1 && $ver[1] >= 5) ) { + drupal_set_message(t("Please upgrade SimpleSAMLphp. You are using %ssp_version", array('%ssp_version' => $_simplesamlphp_auth_saml_version)), 'warning'); + } + } + + $roles = user_roles(TRUE); + + $form['simplesamlphp_auth_grp_setup'] = array( + '#type' => 'fieldset', + '#title' => t('Basic Setup'), + '#collapsible' => FALSE, + ); + $form['simplesamlphp_auth_grp_setup']['simplesamlphp_auth_activate'] = array( + '#type' => 'checkbox', + '#title' => t('Activate authentication via SimpleSAMLphp'), + '#default_value' => variable_get('simplesamlphp_auth_activate', FALSE), + '#description' => t('Checking this box before configuring the module could lock you out of Drupal.'), + ); + $form['simplesamlphp_auth_grp_setup']['simplesamlphp_auth_installdir'] = array( + '#type' => 'textfield', + '#title' => t('Installation directory (default: sites/all/modules/simplesamlphp_auth/simplesamlphp)'), + '#default_value' => variable_get('simplesamlphp_auth_installdir', 'sites/all/modules/simplesamlphp_auth/simplesamlphp'), + '#description' => t('The base directory of simpleSAMLphp. Absolute path with no trailing slash.'), + ); + $form['simplesamlphp_auth_grp_setup']['simplesamlphp_auth_authsource'] = array( + '#type' => 'textfield', + '#title' => t('Autenticaton source for this SP (default: default-sp)'), + '#default_value' => variable_get('simplesamlphp_auth_authsource', 'default-sp'), + '#description' => t('The name of the source to use from authsources.php'), + ); + $form['simplesamlphp_auth_grp_setup']['simplesamlphp_auth_forcehttps'] = array( + '#type' => 'checkbox', + '#title' => t('Force https for login links'), + '#default_value' => variable_get('simplesamlphp_auth_forcehttps', TRUE), + '#description' => t('Should be enabled on production sites.'), + ); + + $form['simplesamlphp_auth_grp_user'] = array( + '#type' => 'fieldset', + '#title' => t('User Info and Syncing'), + '#collapsible' => FALSE, + ); + $form['simplesamlphp_auth_grp_user']['simplesamlphp_auth_user_name'] = array( + '#type' => 'textfield', + '#title' => t('Which attribute from simpleSAMLphp should be used as user\'s name'), + '#default_value' => variable_get('simplesamlphp_auth_user_name', 'uid'), + '#description' => t('Example: eduPersonPrincipalName or displayName
If the attribute is multivalued, the first value will be used.'), + '#required' => TRUE, + ); + $form['simplesamlphp_auth_grp_user']['simplesamlphp_auth_unique_id'] = array( + '#type' => 'textfield', + '#title' => t('Which attribute from simpleSAMLphp should be used as unique identifier for the user'), + '#default_value' => variable_get('simplesamlphp_auth_unique_id', 'NameID'), + '#description' => t('Example: eduPersonPrincipalName or eduPersonTargetedID
If the attribute is multivalued, the first value will be used.'), + '#required' => TRUE, + ); + $form['simplesamlphp_auth_grp_user']['simplesamlphp_auth_mailattr'] = array( + '#type' => 'textfield', + '#title' => t('Which attribute from simpleSAMLphp should be used as user mail address'), + '#default_value' => variable_get('simplesamlphp_auth_mailattr', 'email'), + '#description' => t('Example: email
If the user attribute is multivalued, the first value will be used.'), + ); + $form['simplesamlphp_auth_grp_user']['simplesamlphp_auth_first_name'] = array( + '#type' => 'textfield', + '#title' => t('Which attribute from simpleSAMLphp should be used as first name'), + '#default_value' => variable_get('simplesamlphp_auth_first_name', 'gn'), + '#description' => t('Example: gn
If the user attribute is multivalued, the first value will be used.'), + ); + $form['simplesamlphp_auth_grp_user']['simplesamlphp_auth_rolepopulation'] = array( + '#type' => 'textarea', + '#title' => t('Automatic role population from simpleSAMLphp attributes'), + '#default_value' => variable_get('simplesamlphp_auth_rolepopulation', ''), + '#description' => t('A pipe separated list of rules.
Example: roleid1:condition1|roleid2:contition2...
For instance: 1:eduPersonPrincipalName,@=,uninett.no;affiliation,=,employee|2:mail,=,andreas@uninett.no'), + ); + $form['simplesamlphp_auth_grp_user']['simplesamlphp_auth_roleevaleverytime'] = array( + '#type' => 'checkbox', + '#title' => t('Reevaluate roles every time the user logs in.'), + '#default_value' => variable_get('simplesamlphp_auth_roleevaleverytime', 0), + '#description' => t('NOTE: This means users could loose any roles that have been assigned manually in Drupal.'), + ); + + $form['simplesamlphp_auth_grp_reg'] = array( + '#type' => 'fieldset', + '#title' => t('User Provisioning'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['simplesamlphp_auth_grp_reg']['simplesamlphp_auth_registerusers'] = array( + '#type' => 'checkbox', + '#title' => t('Register users (i.e., auto-provisioning)'), + '#default_value' => variable_get('simplesamlphp_auth_registerusers', TRUE), + '#description' => t('Determines wether or not the module should automatically create/register new Drupal accounts for users that authenticate using SimpleSAMLphp. Unless you\'ve done some custom work to provision Drupal accounts with the necessary authmap entries you will want this checked.

NOTE: If unchecked each user must already have been provisioned a Drupal account with an appropriate entry in the authmap table before logging in. Otherwise they will receive a notice and be denied access. Be aware that simply creating a Drupal account will not create the necessary entry in the authmap table.'), + ); + + $form['simplesamlphp_auth_grp_auth'] = array( + '#type' => 'fieldset', + '#title' => t('Drupal Authentication'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['simplesamlphp_auth_grp_auth']['simplesamlphp_auth_allowsetdrupalpwd'] = array( + '#type' => 'checkbox', + '#title' => t('Allow SAML users to set Drupal passwords.'), + '#default_value' => variable_get('simplesamlphp_auth_allowsetdrupalpwd', FALSE), + '#description' => t('Check this box if you want to let people set passwords for their local Drupal accounts. This will allow users to log in using either SAML or a local Drupal account. Disabling this removes the password change fields from the user profile form.
NOTE: In order for them to login using their local Drupal password you must allow local logins with the settings below.'), + ); + $form['simplesamlphp_auth_grp_auth']['simplesamlphp_auth_allowdefaultlogin'] = array( + '#type' => 'checkbox', + '#title' => t('Allow authentication with local Drupal accounts'), + '#default_value' => variable_get('simplesamlphp_auth_allowdefaultlogin', TRUE), + '#description' => t('Check this box if you want to let people log in with local Drupal accounts (without using simpleSAMLphp). If you want to restrict this privilege to certain users you can enter the Drupal user IDs in the field below.'), + ); + $form['simplesamlphp_auth_grp_auth']['simplesamlphp_auth_allowdefaultloginroles'] = array( + '#type' => 'select', + '#size' => 3, + '#options' => $roles, + '#multiple' => TRUE, + '#title' => t('Which ROLES should be allowed to login with local accounts?'), + '#default_value' => variable_get('simplesamlphp_auth_allowdefaultloginroles', ''), + '#description' => t('Roles that should be allowed to login without simpleSAMLphp. Examples are dev/admin roles or guest roles.'), + ); + $form['simplesamlphp_auth_grp_auth']['simplesamlphp_auth_allowdefaultloginusers'] = array( + '#type' => 'textfield', + '#title' => t('Which users should be allowed to login with local accounts?'), + '#default_value' => variable_get('simplesamlphp_auth_allowdefaultloginusers', ''), + '#description' => t('Example: 1,2,3
A comma-separated list of user IDs that should be allowed to login without simpleSAMLphp. If left blank, all local accounts can login.'), + ); + $form['simplesamlphp_auth_grp_auth']['simplesamlphp_auth_logoutgotourl'] = array( + '#type' => 'textfield', + '#title' => t('Optionally, specify a URL for users to go to after logging out'), + '#default_value' => variable_get('simplesamlphp_auth_logoutgotourl', ''), + '#description' => t('Example: ' . $base_url), + ); + + return system_settings_form($form); +} + +/** + * Implements hook_form_alter(). + */ +function simplesamlphp_auth_form_alter(&$form, $form_state, $form_id) { + if (!_simplesamlphp_auth_isEnabled()) { + // Exit without executing. + return; + } + + if ($form_id == 'user_login_block') { + $link = l('Connexion via mon compte citoyen', 'saml_login'); + //$links = $form['links']['#markup']; + //$links = str_replace('', '
  • ' . $link . '
  • ', $links); + $button = '
    '; + $form['links']['#markup'] = $button; + unset($form['pass']); + unset($form['name']); + unset($form['submit']); + unset($form['actions']); + } + + if ($form_id == 'user_account_form') { + $link = l('Federated Log In', 'saml_login'); + $links = $form['links']['#markup']; + $links = str_replace('', '
  • ' . $link . '
  • ', $links); + $form['links']['#markup'] = $links; + } + + // If the user has a simplesamlphp_auth authmap record, then don't require them to know their Drupal password. + // This will allow them to change their e-mail address, and set a Drupal password if they want to (and are allowed). + if ((isset($form['#user']->init) && $form['#user']->init) && (_simplesaml_auth_user_has_authmap($form['#user']->init) && $form_id == 'user_profile_form')) { + + unset($form['account']['current_pass']); + unset($form['account']['current_pass_required_values']); + $form['#validate'] = array_diff($form['#validate'], array('user_validate_current_pass')); + + // If the user is a simplesamlphp_auth user and is NOT allowed to set their Drupal password, remove the fields from the form. + if (!variable_get('simplesamlphp_auth_allowsetdrupalpwd')) { + unset($form['account']['pass']); + } + + } +} + +/** + * Implements hook_block_view(). + */ +function simplesamlphp_auth_block_view($delta = '') { + + if (!_simplesamlphp_auth_isEnabled()) { + // Exit without executing. + return; + } + + switch ($delta) { + case 0: + $block = array('subject' => t('simpleSAMLphp login'), + 'content' => _simplesamlphp_auth_generate_block_text()); + break; + } + return $block; +} + +/** + * Implements hook_block_info(). + */ +function simplesamlphp_auth_block_info() { + $block = array( + array( + 'info' => t('simpleSAMLphp authentication'), + 'cache' => DRUPAL_NO_CACHE, + ) + ); + return $block; +} + +/**************************************************************************** + * Private functions ******************************************************** + ****************************************************************************/ + +/** + * Checks to see if authentication via SimpleSAMLphp should be activated + * + * @param bShowInactiveMsg + * Whether to display the "module not activated" message + * + * @return + * TRUE/FALSE + */ +function _simplesamlphp_auth_isEnabled($bShowInactiveMsg=FALSE) { + GLOBAL $user; + + $failure = NULL; + $isActivated = variable_get('simplesamlphp_auth_activate'); + $basedir = variable_get('simplesamlphp_auth_installdir', 'sites/all/modules/simplesamlphp_auth/simplesamlphp'); + + if (!$isActivated) { + $adminPath = array_keys(simplesamlphp_auth_admin_paths()); + $failure = t('SimpleSAMLphp authentication is NOT yet activated. It can be activated on the ' . l('configuration page', $adminPath[0]) . '.'); + + watchdog('simplesamlphp_auth', $failure, NULL, WATCHDOG_WARNING); + + } + else { + + // Make sure we know where SimpleSAMLphp is. + if (!file_exists($basedir)) { + $failure = t('SimpleSAMLphp could not be found at %basedir . The simplesamlphp_auth module cannot function until the path to the local SimpleSAMLphp instance is configured.', array('%basedir' => $basedir)); + + watchdog('simplesamlphp_auth', $failure, NULL, WATCHDOG_WARNING); + + } + + } + + // If there were no failures, then it should be activated + if (!$failure) { + return TRUE; + } + else { + + // communicate but don't be too annoying + if ( $bShowInactiveMsg && (1 == $user->uid || user_access('access administration pages')) && ( preg_match('/admin\/people/', request_uri()) || preg_match('/admin\/modules/', request_uri()) || preg_match('/admin\/config/', request_uri()) ) ) { + drupal_set_message($failure); + } + } + + return FALSE; + +} + +/** + * Gets the authname attribute from the SAML assertion. + * + * @return + * The authname attribute. + */ +function _simplesamlphp_auth_get_authname() { + global $_simplesamlphp_auth_saml_attributes; + + $authname = ''; + + error_log(print_r($_simplesamlphp_auth_saml_attributes, TRUE)); + // Check if valid local session exists.. + if (isset($_simplesamlphp_auth_saml_attributes)) { + _simplesaml_auth_debug(t('_simplesamlphp_auth_get_authname: Valid local session exist')); + if (isset($_simplesamlphp_auth_saml_attributes[variable_get('simplesamlphp_auth_unique_id', 'NameID')])) { + $authname = $_simplesamlphp_auth_saml_attributes[variable_get('simplesamlphp_auth_unique_id', 'NameID')][0]; + } + else { + throw new Exception(t('error in simplesamlphp_auth.module: no valid unique id attribute set')); + } + } + return $authname; +} + +/** + * Gets the default name attribute from the SAML assertion. + * + * @return + * The name attribute. + */ +function _simplesamlphp_auth_get_default_name() { + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + + $default_name = ''; + + // Check if valid local session exists.. + if ($_simplesamlphp_auth_as->isAuthenticated() ) { + $auth_user_name_attr = variable_get('simplesamlphp_auth_user_name', 'eduPersonPrincipalName'); + if ((!isset($_simplesamlphp_auth_saml_attributes[$auth_user_name_attr])) || + (!isset($_simplesamlphp_auth_saml_attributes[$auth_user_name_attr][0])) || + ($_simplesamlphp_auth_saml_attributes[$auth_user_name_attr][0] == '')) { + throw new Exception(t('There was no set attribute named "%auth_user_name_attr"', + array( + '%auth_user_name_attr' => $auth_user_name_attr, + ))); + } + $default_name = $_simplesamlphp_auth_saml_attributes[$auth_user_name_attr][0]; + } + return $default_name; +} + +/** + * Gets an attribute value. + * + * @return + * The mail attribute. + */ +function _simplesamlphp_auth_get_attr($attr_name, $default) { + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + $value = ''; + // Check if valid local session exists.. + if ($_simplesamlphp_auth_as->isAuthenticated()) { + if (isset($_simplesamlphp_auth_saml_attributes[variable_get($attr_name, $default)])) { + $value = $_simplesamlphp_auth_saml_attributes[variable_get($attr_name, $default)][0]; + } + else { + throw new Exception(t("Error in simplesamlphp_auth.module: No valid $attr_name attribute set.")); + } + } + + return $value; +} + +/** + * Forces HTTPS connections. + */ +function _simplesamlphp_auth_forcehttps_rewrite($url) { + if (variable_get('simplesamlphp_auth_forcehttps', TRUE)) { + $url = str_replace('http://', 'https://', $url); + _simplesaml_auth_debug('forcehttps rewrite: ' . $url); + } + + return $url; +} + +/** + * Generates the text for the log in block. + */ +function _simplesamlphp_auth_generate_block_text() { + global $_simplesamlphp_auth_as; + $block_content = ''; + global $user; + + if (!_simplesamlphp_auth_isEnabled()) { + // Exit without executing. + return; + } + + // Check if valid local session exists.. + if ($_simplesamlphp_auth_as->isAuthenticated()) { + $block_content .= '

    Logged in as: ' . $user->name . '
    ' . l('Log Out', 'user/logout') . '

    '; + } + else { + $block_content .= '

    ' . l('Federated Log In', 'saml_login') . '

    '; + } + + return $block_content; +} + +/** + * Evaluates a role rule. + * + * @param $roleruleevaluation + * An array containing the role rule to evaluate. + * @param $attributes + * An array containing the identity attributes. + * + * @return + * An array containing role value and the attribute, or FALSE. + */ +function _simplesamlphp_auth_evaulaterolerule($roleruleevaluation, $attributes) { + _simplesaml_auth_debug(t('Evaluate rule (key=%key,operator=%op,value=%val)', array('%key' => $roleruleevaluation[0], '%op' => $roleruleevaluation[1], '%val' => $roleruleevaluation[2]))); + + if (!array_key_exists($roleruleevaluation[0], $attributes)) { + return FALSE; + } + $attribute = $attributes[$roleruleevaluation[0]]; + + switch ($roleruleevaluation[1]) { + case '=' : + return in_array($roleruleevaluation[2], $attribute); + + case '@=' : + $dc = explode('@', $attribute[0]); + if (count($dc) != 2) { + return FALSE; + } + return ($dc[1] == $roleruleevaluation[2]); + } + + return FALSE; +} + +/** + * Performs role population. + * + * @param $rolemap + * A string containing the role map. + * + * @return + * An array containing user's roles. + */ +function _simplesamlphp_auth_rolepopulation($rolemap) { + global $_simplesamlphp_auth_as; + global $_simplesamlphp_auth_saml_attributes; + $roles = array(); + + _simplesaml_auth_debug(t('Rolemap: %rolemap', array('%rolemap' => $rolemap))); + + // Check if valid local session exists.. + if ($_simplesamlphp_auth_as->isAuthenticated()) { + $attributes = $_simplesamlphp_auth_saml_attributes; + + if (empty($rolemap)) return $roles; + + _simplesaml_auth_debug(t('Evaluate rolemap: %rolemap', array('%rolemap' => $rolemap))); + + $rolerules = explode('|', $rolemap); + + foreach ($rolerules AS $rolerule) { + _simplesaml_auth_debug(t('Evaluate role rule: %rolerule', array('%rolerule' => $rolerule))); + + $roleruledecompose = explode(':', $rolerule); + + $roleid = $roleruledecompose[0]; + $roleruleevaluations = explode(';', $roleruledecompose[1]); + + $addnew = TRUE; + foreach ($roleruleevaluations AS $roleruleevaluation) { + + _simplesaml_auth_debug(t('Evaluate role evaulation: %roleruleeval', array('%roleruleeval' => $roleruleevaluation))); + + $roleruleevaluationdc = explode(',', $roleruleevaluation); + if (!_simplesamlphp_auth_evaulaterolerule($roleruleevaluationdc, $attributes)) { + $addnew = FALSE; + } + } + if ($addnew) { + $roles[$roleid] = $roleid; + _simplesaml_auth_debug(t('Add new role: %roleid', array('%roleid' => $roleid))); + } + + } + } + return $roles; +} + +/** + * See if the user has an authmap record for simplesamlphp_auth + */ +function _simplesaml_auth_user_has_authmap($authname) { + $authmaps = user_get_authmaps($authname); + + $return = 0; + + if (is_array($authmaps)) { + $return = in_array('simplesamlphp_auth', array_keys($authmaps)); + } + + return $return; + +} + +/** + * This helper function is used by developers to debug the form API workflow in this module. + */ +function _simplesaml_auth_debug($message) { + watchdog('simplesamlphp', $message, NULL, WATCHDOG_DEBUG); +} + +/** + * Helper function for logging out a user that is has a active session in Drupal but not with simpleSAML. + */ +function _simplesamlphp_auth_destroy_drupal_session() { + global $user; + + watchdog('user', 'Session closed for %name.', array('%name' => $user->name)); + + // Destroy the current session: + session_destroy(); + // Only variables can be passed by reference workaround. + $NULL = NULL; + user_module_invoke('logout', $NULL, $user); + + // Load the anonymous user. + $user = drupal_anonymous_user(); + + drupal_goto(); +} + +/**************************************************************************** + * Public functions ********************************************************* + ****************************************************************************/ + +/** + * Determine if the current user is authenticated through SAML. + * + * @return + * TRUE if the current user is authenticated through SAML. FALSE otherwise. + */ +function simplesamlphp_auth_is_authenticated() { + global $_simplesamlphp_auth_as; + + // Assume that the user isn't authenticated until proven otherwise. + $authenticated = FALSE; + + // If the associated global variable exists, and the auth flag is set, note it. + if (isset($_simplesamlphp_auth_as) && $_simplesamlphp_auth_as->isAuthenticated()) { + $authenticated = TRUE; + } + + // Return the result. + return $authenticated; +} + +/** + * Return any attributes provided by the SAML IDP. + * + * @param $attribute + * The attribute whose value to return. Can be skipped if all attribute + * values are requested. + * + * @return + * If an attribute was provided, the value of the attribute is returned. + * Otherwise, an array of all attribute values is returned, keyed by + * attribute. + */ +function simplesamlphp_auth_get_attributes($attribute = NULL) { + global $_simplesamlphp_auth_saml_attributes; + + if (isset($attribute)) { + + // Initially, assume that there's nothing to return. + $result = NULL; + + // If the specified attribute is set, grab it. + if (isset($_simplesamlphp_auth_saml_attributes)) { + if (isset($_simplesamlphp_auth_saml_attributes[$attribute])) { + $result = $_simplesamlphp_auth_saml_attributes[$attribute]; + } + } + } + + // No specific attribute was requested; return all of them. + else { + + // Initially, assume that there's nothing to return. + $result = array(); + + // If the global array exists, return it. + if (isset($_simplesamlphp_auth_saml_attributes)) { + $result = $_simplesamlphp_auth_saml_attributes; + } + } + + // Return whatever we've got.` + return $result; +} + diff --git a/drupal/simplesamlphp_auth/simplesamlphp_auth.rules.inc b/drupal/simplesamlphp_auth/simplesamlphp_auth.rules.inc new file mode 100644 index 0000000..9d25d69 --- /dev/null +++ b/drupal/simplesamlphp_auth/simplesamlphp_auth.rules.inc @@ -0,0 +1,34 @@ + t('User'), + 'module' => 'simplesamlphp_auth', + ); + + return array( + 'simplesamlphp_auth_rules_event_register' => $defaults + array( + 'label' => t('After registering a new user account via simpleSAMLphp'), + 'group' => t('User'), + 'variables' => array( + 'user' => array('type' => 'user', 'label' => t('Logged in user')), + ), + ), + 'simplesamlphp_auth_rules_event_login' => $defaults + array( + 'label' => t('User has logged in via simpleSAMLphp'), + 'group' => t('User'), + 'variables' => array( + 'user' => array('type' => 'user', 'label' => t('User')), + ), + ), + ); +}