/
spid_pasw.module
1429 lines (1232 loc) · 59.9 KB
/
spid_pasw.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
/**
* versione PASW - Paolo Bozzo
* versione nata all'interno del progetto SPID per PorteAperteSulWeb
* Le parti aggiunte o modificate sono commentate con @PASW
*/
/* * *********************************
Nota di Bob: considerazioni generali:
- praticamente tutte le stringhe sono da tradurre in italiano
- all'attivazione del modulo, sarebbe opportuno aggiungere ai profili utenti i campi descrittivi previsti da SPID (codice fiscale, data di nascita, etc...)
* @PASW i siti pasw-drupal presentano già questi campi
* studiare un modo per implementarli se non ci sono
cfr. https://api.drupal.org/api/drupal/modules!field!field.crud.inc/function/field_create_field/7
- sarebbe utile allegare la libreria SimpleSAMLPHP ( https://simplesamlphp.org/ ) direttamente al modulo, e fornire una configurazione di default coerente
- documentazione di riferimento:
http://www.agid.gov.it/sites/default/files/circolari/spid-regole_tecniche_v1.pdf
http://www.agid.gov.it/sites/default/files/regole_tecniche/tabella_attributi_idp_v1_0.pdf
Più avanti ci sono altri commenti "Nota di Bob" specifici
*/
/**
* @file
* simpleSAMLphp authentication module for Drupal.
*
* This authentication module is based on the shibboleth authentication module,
* with changes to adopt to use simpleSAMLphp.
*
* ISSUES and TODOs:
* ISSUE: User is always dropped on user page after login, instead of where
* they were when they clicked "Federated Log In". Because of this, deep
* linking to access controlled content does not work. Usability would
* be considerably increased if this were resolved.
* FYI: Drupal now requires knowledge of the local user password in order to
* change e-mail address, etc. This could be an issue for users of
* accounts that are autoprovisioned by this module, though Drupal does
* give users the ability to reset their password to something they know
* via the Request new password feature.
* KLUDGE: Drupal does not kill the session on logout, even with
* drupal_session_destroy_uid(), so I had to use session_destroy().
* @todo Rework the default login limitation logic to use a drupal permission
* rather than a list of UIDs.
* @todo When denying access because the administrator has chosen not to allow
* the module to register/create accounts, the user is told to contact
* the administrator; the message should provide the contact information.
* ISSUE: Until Drupal issue #754560 is resolved users will not see logout
* notices.
*/
/**
* Implements hook_menu().
*/
function spid_pasw_menu() {
$items = array();
$items['admin/config/people/spid_pasw'] = array( //@PASW
'title' => 'Configurazioni SPID pasw',
'description' => 'Controlla le diverse configurazioni del modulo di autenticazione SPID',
'page callback' => 'drupal_get_form',
'page arguments' => array('spid_pasw_settings'),
'access arguments' => array('amministra autenticazione SPID'),
'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
);
$items['saml_login'] = array(
'title' => 'Logon to the site',
'description' => 'Provides a site login page',
'page callback' => 'spid_pasw_loginpage',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['saml_logout'] = array(
'title' => 'Logout to the site',
'description' => 'Provides a site logout page',
'page callback' => 'spid_pasw_logoutpage',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements hook_admin_paths().
*/
function spid_pasw_admin_paths() {
return array('admin/config/people/spid_pasw' => TRUE); //@PASW
}
/**
* Implements hook_page_build
* @PASW aggiunge il bottone SPID alla pagina di login
*
*/
function spid_pasw_page_build(&$page) {
global $user;
static $count = 0;
if (arg(0) == 'user' && (arg(1) == null || arg(1) == 'login') && $user->uid == 0 && $count == 0 && _spid_pasw_isEnabled()) {
$page['content']['spid'] = array (
'#markup' => '<strong>oppure</strong> ' . _spid_pasw_spidbutton(),
'#weight' => 200,
);
$count++;
}
}
/**
* Implements hook_help().
* @PASW
*
*/
function spid_pasw_help($path, $arg) {
switch ($path) {
case 'admin/config/people/spid_pasw':
$output = t('<p>Questo modulo integra il protocollo di autenticazione SPID in Drupal PASW</p>');
$output .= t('<p></p>');
return $output;
}
}
/**
* Implements hook_permission().
*/
function spid_pasw_permission() {
return array(
'amministra autenticazione SPID' => array( //@PASW
'title' => t('Amministra autenticazione SPID'),
'description' => t('Warning: Give to trusted roles only; this permission has security implications.'),
),
);
}
/**
* Represents the Drupal page (saml_logout).
*/
function spid_pasw_logoutpage() {
$state = SimpleSAML_Auth_State::loadState((string) $_REQUEST['LogoutState'], 'MyLogoutState');
$ls = (isset($state['saml:sp:LogoutStatus'])?$state['saml:sp:LogoutStatus']:false); /* Only works for SAML SP */
if ($ls && $ls['Code'] === 'urn:oasis:names:tc:SAML:2.0:status:Success' && !isset($ls['SubCode'])) {
/* Successful logout. */
$msg = t("You have been logged out.");
} else {
/* Logout failed. Tell the user to close the browser. */
$msg = t("We were unable to log you out of all your sessions. To be completely sure that you are logged out, you need to close your web browser.");
}
drupal_set_message(check_plain($msg));
drupal_goto('<front>');
}
/**
* Represents the Drupal page (saml_login), which triggers user authentication against the SimpleSAMLphp service provider.
*/
function spid_pasw_loginpage() {
global $user;
global $base_url;
global $_simplesamlphp_auth_as;
$fail = FALSE;
$output = NULL;
if (!_spid_pasw_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('spid_pasw', '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('spid_pasw', '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('<front>');
}
$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('spid_pasw_returnto', $returnto, time() + 60 * 60);
//setrawcookie('SimpleSAMLSessionID', $returnto, time() + 60 * 60);
}
// Check
// @PASW
if ((isset($_REQUEST['infocert_id']) && $_REQUEST['infocert_id'])) {
$options['saml:idp'] = $_REQUEST['infocert_id'];
} elseif ((isset($_REQUEST['poste_id']) && $_REQUEST['poste_id'])) {
$options['saml:idp'] = $_REQUEST['poste_id'];
} elseif ((isset($_REQUEST['tim_id']) && $_REQUEST['tim_id'])) {
$options['saml:idp'] = $_REQUEST['tim_id'];
} elseif ((isset($_REQUEST['sielte_id']) && $_REQUEST['sielte_id'])) {
$options['saml:idp'] = $_REQUEST['sielte_id'];
} elseif ((isset($_REQUEST['aruba_id']) && $_REQUEST['aruba_id'])) {
$options['saml:idp'] = $_REQUEST['aruba_id'];
} elseif ((isset($_REQUEST['namirial_id']) && $_REQUEST['namirial_id'])) {
$options['saml:idp'] = $_REQUEST['namirial_id'];
} elseif ((isset($_REQUEST['register_id']) && $_REQUEST['register_id'])) {
$options['saml:idp'] = $_REQUEST['register_id'];
} elseif ((isset($_REQUEST['intesa_id']) && $_REQUEST['intesa_id'])) {
$options['saml:idp'] = $_REQUEST['intesa_id'];
} elseif ((isset($_REQUEST['lepida_id']) && $_REQUEST['lepida_id'])) {
$options['saml:idp'] = $_REQUEST['lepida_id'];
} else {
drupal_set_message(t('We\'re sorry. There was a problem. The issue has been logged for the administrator.'));
drupal_goto('<front>');
}
// Require the user to be authenticated.
/*
$authformat = variable_get('spid_pasw_authuri', 'https://www.spid.gov.it/%s');
$authlevel = variable_get('spid_pasw_authlevel', 'SpidL1');
$options['saml:AuthnContextClassRef'] = sprintf($authformat, $authlevel);
$options['samlp:RequestedAuthnContext'] = array("Comparison" => "minimum");
*/
$options['ErrorURL'] = base_path();
$_simplesamlphp_auth_as->requireAuth($options);
// 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['spid_pasw_returnto']) && $_COOKIE['spid_pasw_returnto']) {
// use the cookie for the ReturnTo
$gotourl = $_COOKIE['spid_pasw_returnto'];
// unset the cookie
setrawcookie('spid_pasw_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 $output;
}
function _spid_pasw_get_cf_key($name) {
$a = field_info_field($name);
if (!$a) {
echo "errore: necessario campo 'Codice Fiscale'";
exit;
}
return $a['type'] == 'text'? 'value' : 'code';
}
function _spid_pasw_set_field($field, $value, $cf = FALSE) {
global $user;
if (empty($field) || !property_exists($user, $field))
return;
$key = 'value';
if ($cf) $key = _spid_pasw_get_cf_key($field);
$ptr = &$user->$field;
$ptr[LANGUAGE_NONE][0][$key] = $value;
}
/**
* Implements hook_init().
* @PASW uso del lock su file per impedire esecuzioni contemporanee del codice
* @PASW scrittura accessi nel log
*/
function spid_pasw_init() {
global $user;
global $_simplesamlphp_auth_as;
global $_simplesamlphp_auth_saml_attributes;
global $_simplesamlphp_auth_saml_config;
global $_simplesamlphp_auth_saml_version;
$access = 0;
// $semaphore = sem_get(111222);
if (!_spid_pasw_isEnabled(TRUE)) {
// Exit without initializing.
return;
}
// Get the simplesamlphp session.
$basedir = variable_get('spid_pasw_installdir', '/var/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('spid_pasw_authsource', 'default-sp'));
$_simplesamlphp_auth_saml_attributes = $_simplesamlphp_auth_as->getAttributes();
$file = fopen(file_directory_temp()."/spidcheck","w+");
flock($file,LOCK_EX);
//sem_acquire($semaphore);
if ($user->uid == 0) {
// User is not logged in to Drupal.
if ($_simplesamlphp_auth_as->isAuthenticated()) {
// User is logged in - SimpleSAMLphp (but not Drupal).
// Get unique identifier from saml attributes.
$authname = _spid_pasw_get_authname();
_simplesaml_auth_debug(t('Authname is [%authname] userid is [%uid]', array('%authname' => $authname, '%uid' => $user->uid)));
if (!empty($authname)) {
$access = 1;
$_SESSION['spid-access'] = TRUE;
// User is logged in with SAML authentication and we got the unique identifier.
// Try to log into Drupal.
SimpleSAML_Logger::alert('Utente ' . $authname . ' (' . _spid_pasw_get_fiscal_number(0) . ') autenticato via SPID');
_simplesaml_auth_debug(t('Load user [%authname]', array('%authname' => $authname)));
// Retrieve user by name and attempt to log the user in.
$ext_user = user_load_by_name($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('spid_pasw_registerusers', TRUE)) {
// We are allowed to register new users.
_simplesaml_auth_debug(t('Register [%authname]', array('%authname' => $authname)));
user_external_login_register($authname, 'spid_pasw');
if ($user) {
// Populate roles based on configuration setting.
$roles = _spid_pasw_rolepopulation(variable_get('spid_pasw_rolepopulation', ''));
$userinfo = array(
'roles' => $roles,
);
// @PASW gestione attributi->campi
$cognome = variable_get('spid_pasw_lastname','field_cognome');
_spid_pasw_set_field($cognome,$_simplesamlphp_auth_saml_attributes['familyName'][0]);
$nome = variable_get('spid_pasw_firstname','field_nome');
_spid_pasw_set_field($nome,$_simplesamlphp_auth_saml_attributes['name'][0]);
$cf = variable_get('spid_pasw_cf','field_codice_fiscale');
_spid_pasw_set_field($cf,substr($_simplesamlphp_auth_saml_attributes['fiscalNumber'][0],6),TRUE);
$date = variable_get('spid_pasw_date','field_data_di_nascita');
if (isset($_simplesamlphp_auth_saml_attributes['dateOfBirth'])
&& property_exists($user,$date)) {
$ar1 = explode('-', $_simplesamlphp_auth_saml_attributes['dateOfBirth'][0]);
$ar2 = array($ar1[2], $ar1[1], $ar1[0]);
$ptr = &$user->$date;
$ptr[LANGUAGE_NONE][0]['value'] = implode('/', $ar2);
}
$place = variable_get('spid_pasw_place','field_luogo_di_nascita');
if (isset($_simplesamlphp_auth_saml_attributes['placeOfBirth']) && property_exists($user,$place)) {
$ptr = &$user->$place;
$ptr[LANGUAGE_NONE][0]['value'] = $_simplesamlphp_auth_saml_attributes['placeOfBirth'][0];
}
$prov = variable_get('spid_pasw_province','field_provincia_di');
if (isset($_simplesamlphp_auth_saml_attributes['countyOfBirth']) && property_exists($user,$prov)) {
$ptr = &$user->$prov;
$ptr[LANGUAGE_NONE][0]['value'] = $_simplesamlphp_auth_saml_attributes['countyOfBirth'][0];
}
$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));
//sem_release($semaphore);
flock($file,LOCK_UN);fclose($file);
$_simplesamlphp_auth_as->logout(base_path());
return;
}
} else {
// If successfully logged into Drupal.
// See if we're supposed to re-evaluate role assignments.
/* removed roles re-evaluation */
// No need to evaluate roles, populate the user object.
// don't login if user disabled
if ($ext_user->status == 0) {
drupal_set_message('utente disabilitato');
SimpleSAML_Logger::alert('Utente disabilitato ' . $authname . ' autenticato ma non loggato');
//sem_release($semaphore);
flock($file,LOCK_UN);fclose($file);
$_simplesamlphp_auth_as->logout(base_path());
return;
}
$user = $ext_user;
if (module_exists('rules')) {
rules_invoke_event('spid_pasw_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.
} // End if user->uid.
//sem_release($semaphore);
flock($file,LOCK_UN);fclose($file);
if ($access == 0 && isset($_SESSION['spid-access']) && $_SESSION['spid-access']) {
$_SESSION['spid-access'] = FALSE;
$serv = variable_get('spid_pasw_servicedir', '');
if (!empty($serv) && drupal_valid_path($serv))
drupal_goto($serv);
}
}
/**
* Implements hook_user_insert().
*/
function spid_pasw_user_insert(&$edit, $account, $category = NULL) {
global $_simplesamlphp_auth_as;
global $_simplesamlphp_auth_saml_attributes;
if (!_spid_pasw_isEnabled()) {
// Exit without initializing.
return;
}
if ($category == 'account') {
// If user registration has a valid session...
if ($_simplesamlphp_auth_as->isAuthenticated()) {
/* @PASW removed code
// Get name from default attributes.
try {
_simplesaml_auth_debug(t('Registering user [%acctname]', array('%acctname' => $account->name)));
$account->name = _spid_pasw_get_fiscal_number($account->uid);
} catch (Exception $e) {
drupal_set_message(t('Your user name was not provided by your identity provider (IDP).'), "error");
watchdog('spid_pasw', $e->getMessage(), NULL, WATCHDOG_CRITICAL);
}
db_update('users')
->fields(array('name' => $account->name))
->condition('uid', $account->uid)
->execute();
_simplesaml_auth_debug(t('Updating username [%acctname]', array('%acctname' => $account->name)));
*/
// Get mail from default attribute.
try {
$mail_address = _spid_pasw_get_mail();
} catch (Exception $e) {
drupal_set_message(t('Your e-mail address was not provided by your identity provider (IDP).'), "error");
watchdog('spid_pasw', $e->getMessage(), NULL, WATCHDOG_CRITICAL);
}
if (!empty($mail_address)) {
db_update('users')
->fields(array('mail' => $mail_address))
->condition('uid', $account->uid)
->execute();
}
if (module_exists('rules')) {
rules_invoke_event('spid_pasw_rules_event_register', $account);
}
_simplesaml_auth_debug(t('Updating mail [%mailaddr]', array('%mailaddr' => $mail_address)));
}
}
}
/**
* Implements hook_user_logout().
*/
function spid_pasw_user_logout($account) {
global $user;
global $_simplesamlphp_auth_as;
global $_simplesamlphp_auth_saml_attributes;
global $base_url;
//$idp = $_simplesamlphp_auth_as->getAuthData('saml:sp:IdP');
if (!empty($_simplesamlphp_auth_saml_attributes)) {
SimpleSAML_Logger::alert("Logout SPID dell'utente $user->name");
//$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('spid_pasw_logoutgotourl', '')) {
$gotourl = variable_get('spid_pasw_logoutgotourl', '');
}
*/
$_simplesamlphp_auth_as->logout(array(
'ReturnTo' => url('saml_logout'),
'ReturnStateParam' => 'LogoutState',
'ReturnStateStage' => 'MyLogoutState'));
}
}
/**
* Implements hook_user_delete().
*/
function spid_pasw_user_delete($account) {
db_delete('authmap')
->condition('uid', $account->uid)
->condition('authname', $account->name)
->execute();
}
/**
* @PASW rileva percorso libreria installata con installatore specifico
*
*/
function _spid_pasw_get_lib_path()
{
$result = '/var/simplesamlphp';
$orig = getcwd();
$root = $_SERVER['DOCUMENT_ROOT'];
chdir ($root);
if (file_exists('simplespidphp')) {
chdir('simplespidphp');
$result = getcwd();
} else if (is_writable('..') && file_exists('../simplespidphp')) {
chdir('../simplespidphp');
$result = getcwd();
}
chdir($orig);
return $result;
}
/**
* Implements settings for the module.
* @PASW inserite specifiche per SPID e libreria
*
*/
function spid_pasw_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['spid_pasw_grp_setup'] = array(
'#type' => 'fieldset',
'#title' => t('Basic Setup'),
'#collapsible' => FALSE,
);
$form['spid_pasw_grp_setup']['spid_pasw_activate'] = array(
'#type' => 'checkbox',
'#title' => t('Attiva autenticazione SPID'),
'#default_value' => variable_get('spid_pasw_activate', FALSE),
'#description' => t('Spuntare per attivare il funzionamento del modulo.'),
);
$default_lib_path = _spid_pasw_get_lib_path();
$form['spid_pasw_grp_setup']['spid_pasw_installdir'] = array(
'#type' => 'textfield',
'#title' => t('Directory della libreria (default: '.$default_lib_path.')'),
'#default_value' => variable_get('spid_pasw_installdir', $default_lib_path),
'#description' => t('Cartella della libreria. Percorso assoluto senza slash finale.<br>IMPORTANTE: se la libreria è installata correttamente deve comparire in automatico il valore appropriato.'),
);
$form['spid_pasw_grp_setup']['spid_pasw_servicedir'] = array(
'#type' => 'textfield',
'#title' => t('Eventuale alias del servizio'),
'#default_value' => variable_get('spid_pasw_servicedir', ''),
'#description' => t('Alias del servizio (per es. per la pagina https://pa.gov.it/servizio scrivere "servizio"), lasciare vuoto per ridirigere alla pagina utente.'),
);
/*
$form['spid_pasw_grp_setup']['spid_pasw_authlevel'] = array(
'#type' => 'radios',
'#title' => t('Livello di autenticazione SPID'),
'#default_value' => variable_get('spid_pasw_authlevel', 'SpidL1'),
'#description' => t('Autenticazione livello 1 o 2'),
'#options' => array(
'SpidL1' => 'Livello 1',
'SpidL2' => 'Livello 2',
),
);
$form['spid_pasw_grp_setup']['spid_pasw_authuri'] = array(
'#type' => 'radios',
'#title' => t('URI di autenticazione SPID'),
'#default_value' => variable_get('spid_pasw_authuri', 'https://www.spid.gov.it/%s'),
'#description' => t('Autenticazione corretta o obsoleta (da provare se la prima non funziona)'),
'#options' => array(
'https://www.spid.gov.it/%s' => 'Autenticazione corretta',
'urn:oasis:names:tc:SAML:2.0:ac:classes:%s' => 'Autenticazione obsoleta',
),
);
*/
$form['spid_pasw_grp_setup']['spid_pasw_authsource'] = array(
'#type' => 'textfield', // fieldset
'#title' => t('Authenticaton source for this SP (default: default-sp)'),
'#default_value' => variable_get('spid_pasw_authsource', 'default-sp'),
'#description' => t('The name of the source to use from simplespidphp/config/authsources.php'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_infocert'] = array(
'#type' => 'hidden', // textfield
'#title' => t('Authenticaton id for Infocert'),
'#default_value' => variable_get('spid_pasw_authsource_infocert', 'https://identity.infocert.it'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_poste'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for Poste'),
'#default_value' => variable_get('spid_pasw_authsource_poste', 'https://posteid.poste.it'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_tim'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for Tim'),
'#default_value' => variable_get('spid_pasw_authsource_tim', 'https://login.id.tim.it/affwebservices/public/saml2sso'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_sielte'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for Sielte'),
'#default_value' => variable_get('spid_pasw_authsource_sielte', 'identity.sieltecloud.it'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_aruba'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for Aruba'),
'#default_value' => variable_get('spid_pasw_authsource_aruba', 'https://loginspid.aruba.it'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_namirial'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for Namirial'),
'#default_value' => variable_get('spid_pasw_authsource_namirial', 'https://idp.namirialtsp.com/idp'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_italia'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for SpidItalia'),
'#default_value' => variable_get('spid_pasw_authsource_italia', 'https://spid.register.it'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_intesa'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for IntesaID'),
'#default_value' => variable_get('spid_pasw_authsource_intesa', 'https://spid.intesa.it'),
);
$form['spid_pasw_grp_setup']['spid_pasw_authsource_lepida'] = array(
'#type' => 'hidden',
'#title' => t('Authenticaton id for LepidaID'),
'#default_value' => variable_get('spid_pasw_authsource_lepida', 'https://id.lepida.it/idp/shibboleth'),
);
$form['spid_pasw_grp_setup']['spid_pasw_forcehttps'] = array(
'#type' => 'checkbox',
'#title' => t('Forzare https'),
'#default_value' => variable_get('spid_pasw_forcehttps', TRUE),
'#description' => t('Va attivato nei siti in produzione.'),
);
$form['spid_pasw_grp_user'] = array(
'#type' => 'hidden', // fieldset
'#title' => t('User Info and Syncing'),
'#collapsible' => FALSE,
);
$form['spid_pasw_grp_user']['spid_pasw_rolepopulation'] = array(
'#type' => 'textarea',
'#title' => t('Automatic role population from simpleSAMLphp attributes'),
'#default_value' => variable_get('spid_pasw_rolepopulation', ''),
'#description' => t('A pipe separated list of rules.<br />Example: <i>roleid1:condition1|roleid2:contition2...</i> <br />For instance: <i>4:all;1:eduPersonPrincipalName,@=,uninett.no;affiliation,=,employee|2:mail,=,andreas@uninett.no</i>'),
);
$form['spid_pasw_grp_user']['spid_pasw_roleevaleverytime'] = array(
'#type' => 'checkbox',
'#title' => t('Reevaluate roles every time the user logs in.'),
'#default_value' => variable_get('spid_pasw_roleevaleverytime', 0),
'#description' => t('NOTE: This means users could loose any roles that have been assigned manually in Drupal.'),
);
$form['spid_pasw_grp_reg'] = array(
'#type' => 'fieldset', // fieldset
'#title' => t('Approvvigionamento utenti'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['spid_pasw_grp_reg']['spid_pasw_registerusers'] = array(
'#type' => 'checkbox', //checkbox
'#title' => t('Registra nuovi utenti'),
'#default_value' => variable_get('spid_pasw_registerusers', TRUE),
'#description' => t('Determina se il modulo deve o no creare un nuovo account Drupal per gli utenti con un codice fiscale non già presente.<br /><br />NOTA: Se non spuntato perché un utente possa accedere deve esistere un account Drupal con specificato il suo codice fiscale.'),
);
$form['spid_pasw_grp_auth'] = array(
'#type' => 'hidden', // fieldset
'#title' => t('Drupal Authentication'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['spid_pasw_grp_auth']['spid_pasw_logoutgotourl'] = array(
'#type' => 'textfield',
'#title' => t('Optionally, specify a URL for users to go to after logging out'),
'#default_value' => variable_get('spid_pasw_logoutgotourl', ''),
'#description' => t('Example: ' . $base_url),
);
$form['spid_pasw_grp_adv'] = array(
'#type' => 'fieldset', // fieldset
'#title' => t('Advanced options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['spid_pasw_grp_adv']['spid_pasw_username_fiscalnumber'] = array(
'#type' => 'checkbox', //checkbox
'#title' => t('Utilizza il codice fiscale come nome utente'),
'#default_value' => variable_get('spid_pasw_username_fiscalnumber', FALSE),
'#description' => t('Determina se il nome utente deve coincidere con il codice fiscale.'),
);
$my_fields = array(''=>'nessun campo');
$fields = field_info_field_map();
foreach ($fields as $name => $field) {
if (isset($field['bundles']['user']) && !empty($field['bundles']['user'])) {
if (isset($field['type']) && ($field['type']=='text'))
$my_fields[$name] = $name;
}
}
$form['spid_pasw_grp_adv']['spid_pasw_firstname'] = array(
'#type' => 'select',
'#title' => t('Scegli il campo per nome'),
'#options' => $my_fields,
'#default_value' => variable_get('spid_pasw_firstname', 'field_nome'),
'#description' => t('Campo da usare per NOME.'),
);
$form['spid_pasw_grp_adv']['spid_pasw_lastname'] = array(
'#type' => 'select',
'#title' => t('Scegli il campo per cognome'),
'#options' => $my_fields,
'#default_value' => variable_get('spid_pasw_lastname', 'field_cognome'),
'#description' => t('Campo da usare per COGNOME.'),
);
$form['spid_pasw_grp_adv']['spid_pasw_place'] = array(
'#type' => 'select',
'#title' => t('Scegli il campo per luogo di nascita'),
'#options' => $my_fields,
'#default_value' => variable_get('spid_pasw_place', 'field_luogo_di_nascita'),
'#description' => t('Campo da usare per LUOGO DI NASCITA.'),
);
$form['spid_pasw_grp_adv']['spid_pasw_prov'] = array(
'#type' => 'select',
'#title' => t('Scegli il campo per provincia di nascita'),
'#options' => $my_fields,
'#default_value' => variable_get('spid_pasw_prov', 'field_provincia_di'),
'#description' => t('Campo da usare per PROVINCIA DI NASCITA.'),
);
$my_fields = array(''=>'nessun campo');
$fields = field_info_field_map();
foreach ($fields as $name => $field) {
if (isset($field['bundles']['user']) && !empty($field['bundles']['user'])) {
//if (isset($field['type']) && (($field['type']=='date') || ($field['type']=='datetime')))
$my_fields[$name] = $name;
}
}
$form['spid_pasw_grp_adv']['spid_pasw_date'] = array(
'#type' => 'select',
'#title' => t('Scegli il campo per data di nascita'),
'#options' => $my_fields,
'#default_value' => variable_get('spid_pasw_date', 'field_data_di_nascita'),
'#description' => t('Campo da usare per DATA DI NASCITA.'),
);
$my_fields = array(''=>'nessun campo');
$fields = field_info_field_map();
foreach ($fields as $name => $field) {
if (isset($field['bundles']['user']) && !empty($field['bundles']['user'])) {
if (isset($field['type']) && (($field['type']=='text') || ($field['type']=='codice_fiscale_basic')))
$my_fields[$name] = $name;
}
}
$form['spid_pasw_grp_adv']['spid_pasw_cf'] = array(
'#type' => 'select',
'#title' => t('Scegli il campo per codice fiscale'),
'#options' => $my_fields,
'#default_value' => variable_get('spid_pasw_cf', 'field_codice_fiscale'),
'#description' => t('Campo da usare per CODICE FISCALE.'),
);
return system_settings_form($form);
}
/**
* Implements hook_block_view().
*/
function spid_pasw_block_view($delta = '') {
if (!_spid_pasw_isEnabled()) {
// Exit without executing.
return;
}
switch ($delta) {
case 0:
$block = array('subject' => '',
'content' => _spid_pasw_generate_block_text());
break;
}
return $block;
}
/**
* Implements hook_block_info().
*/
function spid_pasw_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 _spid_pasw_isEnabled($bShowInactiveMsg = FALSE) {
GLOBAL $user;
$failure = NULL;
$isActivated = variable_get('spid_pasw_activate');
$basedir = variable_get('spid_pasw_installdir', '/var/simplesamlphp');
if (!$isActivated) {
$adminPath = array_keys(spid_pasw_admin_paths());
$failure = t('L\'autenticazione SPID non è ancora stata attivata. Può essere attivata dalla ' . l('pagina di configurazione', $adminPath[0]) . '.');
watchdog('spid_pasw', $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 spid_pasw module cannot function until the path to the local SimpleSAMLphp instance is configured.', array('%basedir' => $basedir));
watchdog('spid_pasw', $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;
}
/**
* @param string original string
* @return string the input string without accents
*/
function _spid_pasw_remove_unwanted_chars($str)
{
$a = array(' ', chr(0xc0), chr(0xc1), chr(0xc2), chr(0xc3), chr(0xc4), chr(0xc5), chr(0xc6), chr(0xc7), chr(0xc8), chr(0xc9), chr(0xca), chr(0xcb), chr(0xcc), chr(0xcd), chr(0xce), chr(0xcf), chr(0xd0), chr(0xd1), chr(0xd2), chr(0xd3), chr(0xd4), chr(0xd5), chr(0xd6), chr(0xd8), chr(0xd9), chr(0xda), chr(0xdb), chr(0xdc), chr(0xdd), chr(0xdf), chr(0xe0), chr(0xe1), chr(0xe2), chr(0xe3), chr(0xe4), chr(0xe5), chr(0xe6), chr(0xe7), chr(0xe8), chr(0xe9), chr(0xea), chr(0xeb), chr(0xec), chr(0xed), chr(0xee), chr(0xef), chr(0xf1), chr(0xf2), chr(0xf3), chr(0xf4), chr(0xf5), chr(0xf6), chr(0xf8), chr(0xf9), chr(0xfa), chr(0xfb), chr(0xfc), chr(0xfd), chr(0xff), chr(0x41), chr(0x61), chr(0x41), chr(0x61), chr(0x41), chr(0x61), chr(0x43), chr(0x63), chr(0x43), chr(0x63), chr(0x43), chr(0x63), chr(0x43), chr(0x63), chr(0x44), chr(0x64), chr(0xd0), chr(0x64), chr(0x45), chr(0x65), chr(0x45), chr(0x65), chr(0x45), chr(0x65), chr(0x45), chr(0x65), chr(0x45), chr(0x65), chr(0x47), chr(0x67), chr(0x47), chr(0x67), chr(0x47), chr(0x67), chr(0x47), chr(0x67), chr(0x48), chr(0x68), chr(0x48), chr(0x68), chr(0x49), chr(0x69), chr(0x49), chr(0x69), chr(0x49), chr(0x69), chr(0x49), chr(0x69), chr(0x49), chr(0x69), chr(0x3f), chr(0x3f), chr(0x4a), chr(0x6a), chr(0x4b), chr(0x6b), chr(0x4c), chr(0x6c), chr(0x4c), chr(0x6c), chr(0x4c), chr(0x6c), chr(0x3f), chr(0x3f), chr(0x4c), chr(0x6c), chr(0x4e), chr(0x6e), chr(0x4e), chr(0x6e), chr(0x4e), chr(0x6e), chr(0x3f), chr(0x4f), chr(0x6f), chr(0x4f), chr(0x6f), chr(0x4f), chr(0x6f), chr(0xa6), chr(0xb6), chr(0x52), chr(0x72), chr(0x52), chr(0x72), chr(0x52), chr(0x72), chr(0x53), chr(0x73), chr(0x53), chr(0x73), chr(0x53), chr(0x73), chr(0xa9), chr(0xb9), chr(0x54), chr(0x74), chr(0x54), chr(0x74), chr(0x54), chr(0x74), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x57), chr(0x77), chr(0x59), chr(0x79), chr(0xbc), chr(0x5a), chr(0x7a), chr(0x5a), chr(0x7a), chr(0xae), chr(0xbe), chr(0x3f), chr(0x83), chr(0x4f), chr(0x6f), chr(0x55), chr(0x75), chr(0x41), chr(0x61), chr(0x49), chr(0x69), chr(0x4f), chr(0x6f), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x55), chr(0x75), chr(0x3f), chr(0x3f), chr(0x3f), chr(0x3f), chr(0x3f), chr(0x3f));
$b = array('_', 'A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o');
return str_replace($a, $b, $str);
}
/**
* Gets the authname attribute from the SAML assertion.
* Auth_name can't be spidCode because a singol user can have tree SPID authentication
* with tree different idp (so he has a single user but tree spidCode)
*
* @return
* The authname attribute.
*/
function _spid_pasw_get_authname() {
global $_simplesamlphp_auth_saml_attributes;
$cf_name = variable_get('spid_pasw_cf', 'field_codice_fiscale');
$table = 'field_data_' . $cf_name;
//drupal_set_message($table);
if ((variable_get('spid_pasw_username_fiscalnumber', FALSE) == TRUE)
|| !(db_table_exists($table))) {
return _spid_pasw_get_authname_fiscalnumber();
}
$tmp_user = NULL;
if (isset($_simplesamlphp_auth_saml_attributes['fiscalNumber']) == false)
throw new Exception(t('error in spid_pasw.module: no valid unique id attribute set'));
$fiscal_number = substr($_simplesamlphp_auth_saml_attributes['fiscalNumber'][0], 6);
$key = _spid_pasw_get_cf_key($cf_name);
$field = $cf_name . '_' . $key;
$query = db_select($table, 'f');
$query->condition($field, $fiscal_number, '=');
$query->join('users', 'u', 'f.entity_id = u.uid');
$query->fields('u', array('name'));
$result = $query->execute();
$array = $result->fetchAssoc();
$authname = isset($array['name']) ? $array['name'] : '';
if ($authname === '') {
$i = 0;
$newname = '';
do {
//if ($tmp_user && $tmp_user->field_codice_fiscale[LANGUAGE_NONE][0]['value']==$fiscal_number)
// return NULL;
$firstname = $_simplesamlphp_auth_saml_attributes['name'][0];
$lastname = $_simplesamlphp_auth_saml_attributes['familyName'][0];
$newname = _spid_pasw_remove_unwanted_chars(sprintf("%s.%s", strtolower($lastname), strtolower($firstname)));
if ($i > 0) $newname = $newname . '.' . $i;
$i++;
} while ($tmp_user = user_load_by_name($newname));
$authname = $newname;
}
return $authname;
}
function _spid_pasw_get_authname_fiscalnumber() {
global $_simplesamlphp_auth_saml_attributes;
$authname = '';
// Check if valid local session exists..
if (isset($_simplesamlphp_auth_saml_attributes)) {
_simplesaml_auth_debug(t('_spid_pasw_get_authname: Valid local session exist'));
if (isset($_simplesamlphp_auth_saml_attributes['fiscalNumber'])) {
$authname = $_simplesamlphp_auth_saml_attributes['fiscalNumber'][0];
$authname = substr($authname, 6);
} else if (isset($_simplesamlphp_auth_saml_attributes['ivaCode'])) {
$authname = $_simplesamlphp_auth_saml_attributes['ivaCode'][0];
} else {
throw new Exception(t('error in spid_pasw.module: no valid unique id attribute set'));
}
}
return $authname;
}
/**
* Gets the default fiscal number from the SAML assertion.
*
* @return
* The name attribute.
*/
function _spid_pasw_get_fiscal_number($account) {
global $_simplesamlphp_auth_as;
global $_simplesamlphp_auth_saml_attributes;