shibboleth.class.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?php
  2. namespace Shibboleth;
  3. use \Redirect;
  4. /**
  5. * Shibboleth main class. Provides access to various Shibboleth sub components and
  6. * provides the high level functionalities.
  7. *
  8. * @license see /license.txt
  9. * @author Laurent Opprecht <laurent@opprecht.info>, Nicolas Rod for the University of Geneva
  10. */
  11. class Shibboleth
  12. {
  13. const NAME = 'shibboleth';
  14. const UNKNOWN_STATUS = -1;
  15. const TEACHER_STATUS = 1;
  16. const STUDENT_STATUS = 5;
  17. static $config = null;
  18. public static function format_status($status)
  19. {
  20. if ($status == Shibboleth::TEACHER_STATUS) {
  21. return 'Teacher';
  22. } else if ($status == Shibboleth::STUDENT_STATUS) {
  23. return 'Student';
  24. } else if ($status == Shibboleth::UNKNOWN_STATUS) {
  25. return 'Unknown';
  26. } else {
  27. return '???';
  28. }
  29. }
  30. /**
  31. *
  32. * @return ShibbolethConfig
  33. */
  34. public static function config()
  35. {
  36. self::$config = self::$config ? self::$config : new ShibbolethConfig();
  37. return self::$config;
  38. }
  39. public static function set_config($config)
  40. {
  41. self::$config = $config;
  42. }
  43. /**
  44. *
  45. * @return ShibbolethSession
  46. */
  47. public static function session()
  48. {
  49. return ShibbolethSession::instance();
  50. }
  51. /**
  52. *
  53. * @return ShibbolethStore
  54. */
  55. public static function store()
  56. {
  57. return ShibbolethStore::instance();
  58. }
  59. /**
  60. *
  61. * @return ShibbolethDisplay
  62. */
  63. public static function display()
  64. {
  65. return ShibbolethDisplay::instance();
  66. }
  67. public static function sys_path()
  68. {
  69. $path = __DIR__.'/../';
  70. return $path;
  71. }
  72. public static function url($path = '')
  73. {
  74. $result = api_get_path('WEB_PATH');
  75. $result .= '/main/auth/shibboleth/' . $path;
  76. return $result;
  77. }
  78. public static function redirect($url = '')
  79. {
  80. if (empty($url)) {
  81. $url = isset($_SESSION['shibb_direct_url']) ? $_SESSION['shibb_direct_url'] : '';
  82. unset($_SESSION['shibb_direct_url']);
  83. /*
  84. * Tests if the user tried to login directly in a protected course before to come here
  85. * (this variable could be set in the modified code of /chamilo/inc/lib/main_api.lib.php)
  86. *
  87. * Note:
  88. * this part was added to give the possibility to access Chamilo directly on a course URL from a link diplayed in a portal.
  89. * This is not a direct Shibboleth related functionnality, but this could be used in a shibbolethized
  90. * Dokeos installation, mainly if you have a SSO system in your network.
  91. * Please note that the file /claroline/inc/lib/main_api.lib.php must be adapted to your Shibboleth settings
  92. * If any interest or question, please contact Nicolas.Rod_at_adm.unige.ch
  93. *
  94. */
  95. }
  96. if ($url) {
  97. //needed to log the user in his courses. Normally it is done by visiting /chamilo/index.php
  98. // $include_path = api_get_path(INCLUDE_PATH);
  99. // require("$include_path/local.inc.php");
  100. //
  101. // if (strpos($url, '?') === false) {
  102. // $url = "$url?";
  103. // }
  104. //
  105. // $rootWeb = api_get_path('WEB_PATH');
  106. // $first_slash_pos = strpos($rootWeb, '/', 8);
  107. // $rootWeb_wo_uri = substr($rootWeb, 0, $first_slash_pos);
  108. // $url = $rootWeb_wo_uri . $course_url . '_stop';
  109. Redirect::go($url);
  110. }
  111. Redirect::home();
  112. }
  113. /**
  114. *
  115. * @param ShibbolethUser $shibb_user
  116. */
  117. public static function save($shibb_user)
  118. {
  119. $shibb_user->status = self::infer_user_status($shibb_user);
  120. $shibb_user->status_request = self::infer_status_request($shibb_user);
  121. $shibb_user->shibb_unique_id = $shibb_user->unique_id;
  122. $shibb_user->shibb_persistent_id = $shibb_user->persistent_id;
  123. $user = User::store()->get_by_shibboleth_id($shibb_user->unique_id);
  124. if (empty($user)) {
  125. $shibb_user->auth_source == self::NAME;
  126. return User::create($shibb_user)->save();
  127. }
  128. $shibb_user->status_request = false;
  129. $fields = self::config()->update_fields;
  130. foreach ($fields as $key => $updatable) {
  131. if ($updatable) {
  132. $user->{$key} = $shibb_user->{$key};
  133. }
  134. }
  135. $user->auth_source == self::NAME;
  136. $user->shibb_unique_id = $shibb_user->shibb_unique_id;
  137. $user->shibb_persistent_id = $shibb_user->shibb_persistent_id;
  138. $user->save();
  139. return $result;
  140. }
  141. /**
  142. * Infer the rights/status the user can have in Chamilo based on his affiliation attribute
  143. *
  144. * @param ShibbolethUser $user
  145. * @return The Chamilo user status, one of TEACHER, STUDENT or UNKNOWN
  146. */
  147. public static function infer_user_status($user)
  148. {
  149. $affiliations = $user->affiliation;
  150. $affiliations = is_array($affiliations) ? $affiliations : array($affiliations);
  151. $map = self::config()->affiliation_status;
  152. $rights = array();
  153. foreach ($affiliations as $affiliation) {
  154. $affiliation = strtolower($affiliation);
  155. if (isset($map[$affiliation])) {
  156. $right = $map[$affiliation];
  157. $rights[$right] = $right;
  158. }
  159. }
  160. $teacher_status = isset($rights[self::TEACHER_STATUS]);
  161. $student_status = isset($rights[self::STUDENT_STATUS]);
  162. //if the user has got teacher rights, we doesn't check anything else
  163. if ($teacher_status) {
  164. return self::TEACHER_STATUS;
  165. }
  166. if ($student_status) {
  167. return self::STUDENT_STATUS;
  168. }
  169. $result = self::config()->default_status;
  170. $result = (int) $result;
  171. $result = ($result == Shibboleth::TEACHER_STATUS || $result == Shibboleth::STUDENT_STATUS) ? $result : Shibboleth::UNKNOWN_STATUS;
  172. return $result;
  173. }
  174. /**
  175. * Return true if the user can ask for a greater status than student.
  176. * This happens for staff members.
  177. *
  178. * @param ShibbolethUser $user
  179. * @return boolean
  180. */
  181. public static function infer_status_request($user)
  182. {
  183. if ($user->status == self::TEACHER_STATUS) {
  184. return false;
  185. }
  186. if ($user->status == self::UNKNOWN_STATUS) {
  187. return true;
  188. }
  189. $config = Shibboleth::config();
  190. $affiliations = $user->affiliation;
  191. $affiliations = is_array($affiliations) ? $affiliations : array($affiliations);
  192. foreach ($affiliations as $affiliation) {
  193. $result = isset($config->affiliation_status_request[$affiliation]) ? $config->affiliation_status_request[$affiliation] : false;
  194. if ($result) {
  195. return true;
  196. }
  197. }
  198. return false;
  199. }
  200. /**
  201. * Sends an email to the Chamilo and Shibboleth administrators in the name
  202. * of the logged-in user.
  203. *
  204. * @param string $subject
  205. */
  206. public static function email_admin($subject, $message)
  207. {
  208. $user = Shibboleth::session()->user();
  209. $firstname = $user['firstname'];
  210. $lastname = $user['lastname'];
  211. $email = $user['email'];
  212. $status = $user['status'];
  213. $status = self::format_status($status);
  214. $signagure = <<<EOT
  215. _________________________
  216. $firstname $lastname
  217. $email
  218. $status
  219. EOT;
  220. $message .= $signagure;
  221. $header = "From: $email \n";
  222. $shibb_admin_email = Shibboleth::config()->admnistrator_email;
  223. if ($shibb_admin_email) {
  224. $header .= "Cc: $shibb_admin_email";
  225. }
  226. $administrator_email = api_get_setting('emailAdministrator');
  227. $result = mail($administrator_email, $subject, $message);
  228. return (bool) $result;
  229. }
  230. }