2008-12-26 18:58:48 +01:00
|
|
|
|
##@file
|
2008-12-03 14:27:30 +01:00
|
|
|
|
# Base package for Lemonldap::NG portal
|
|
|
|
|
|
2009-02-02 09:53:51 +01:00
|
|
|
|
##@class Lemonldap::NG::Portal::Simple
|
2008-12-03 14:27:30 +01:00
|
|
|
|
# Base class for Lemonldap::NG portal
|
2006-12-18 12:32:33 +01:00
|
|
|
|
package Lemonldap::NG::Portal::Simple;
|
|
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
|
|
use Exporter 'import';
|
|
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
|
use MIME::Base64;
|
2008-11-21 18:51:52 +01:00
|
|
|
|
use Lemonldap::NG::Common::CGI;
|
2007-02-11 09:31:56 +01:00
|
|
|
|
use CGI::Cookie;
|
2012-07-12 09:09:41 +02:00
|
|
|
|
use POSIX qw(strftime);
|
2011-03-16 14:58:17 +01:00
|
|
|
|
use Lemonldap::NG::Portal::_i18n; #inherits
|
2014-06-10 18:21:33 +02:00
|
|
|
|
use Lemonldap::NG::Common::Captcha;
|
2014-02-26 11:57:49 +01:00
|
|
|
|
use Lemonldap::NG::Common::Session;
|
2010-01-11 17:04:36 +01:00
|
|
|
|
use Lemonldap::NG::Common::Apache::Session
|
|
|
|
|
; #link protected session Apache::Session object
|
2011-02-07 11:27:36 +01:00
|
|
|
|
use Lemonldap::NG::Common::Safe; #link protected safe Safe object
|
|
|
|
|
use Lemonldap::NG::Common::Safelib;
|
2010-10-08 18:02:43 +02:00
|
|
|
|
use Digest::MD5;
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2009-02-03 10:36:13 +01:00
|
|
|
|
# Special comments for doxygen
|
2009-02-25 19:10:07 +01:00
|
|
|
|
#inherits Lemonldap::NG::Portal::_SOAP
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthApache;
|
2013-10-05 17:55:06 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthAD;
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthCAS;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthChoice;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthDBI;
|
2013-10-05 17:55:06 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthFacebook;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthGoogle;
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthLDAP;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthMulti;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthNull;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthOpenID;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthProxy;
|
2011-11-17 16:38:01 +01:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthRadius;
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthRemote;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthSAML;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthSSL;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::AuthTwitter;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::Display;
|
2010-09-28 07:47:47 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::IssuerDBCAS
|
|
|
|
|
#inherits Lemonldap::NG::Portal::IssuerDBNull
|
|
|
|
|
#inherits Lemonldap::NG::Portal::IssuerDBOpenID
|
|
|
|
|
#inherits Lemonldap::NG::Portal::IssuerDBSAML
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::Menu
|
2012-07-12 23:04:06 +02:00
|
|
|
|
#link Lemonldap::NG::Common::Notification protected notification
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::PasswordDBChoice;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::PasswordDBDBI;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::PasswordDBLDAP;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::PasswordDBNull;
|
2013-10-05 17:55:06 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBAD;
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBChoice;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBDBI;
|
2013-10-05 17:55:06 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBFacebook;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBGoogle;
|
2010-10-02 17:45:10 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBLDAP;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBMulti;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBNull;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBOpenID;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBProxy;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBRemote;
|
|
|
|
|
#inherits Lemonldap::NG::Portal::UserDBSAML;
|
2009-12-10 18:03:57 +01:00
|
|
|
|
#inherits Lemonldap::NG::Portal::PasswordDBDBI
|
2009-05-14 18:19:49 +02:00
|
|
|
|
#inherits Lemonldap::NG::Portal::PasswordDBLDAP
|
2009-02-03 10:36:13 +01:00
|
|
|
|
#inherits Apache::Session
|
2009-02-17 16:22:42 +01:00
|
|
|
|
#link Lemonldap::NG::Common::Apache::Session::SOAP protected globalStorage
|
2009-02-03 10:36:13 +01:00
|
|
|
|
|
2015-12-18 10:31:36 +01:00
|
|
|
|
our $VERSION = '1.9.0';
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2008-12-03 14:27:30 +01:00
|
|
|
|
use base qw(Lemonldap::NG::Common::CGI Exporter);
|
|
|
|
|
our @ISA;
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
# Constants
|
2008-05-30 08:07:37 +02:00
|
|
|
|
use constant {
|
2010-01-11 17:04:36 +01:00
|
|
|
|
|
2010-01-15 23:01:04 +01:00
|
|
|
|
# Portal errors
|
2010-01-11 17:04:36 +01:00
|
|
|
|
# Developers warning, do not use PE_INFO, it's reserved to autoRedirect.
|
|
|
|
|
# If you want to send an information, use $self->info('text').
|
2010-04-29 15:47:57 +02:00
|
|
|
|
PE_IMG_NOK => -5,
|
|
|
|
|
PE_IMG_OK => -4,
|
2010-01-12 10:53:49 +01:00
|
|
|
|
PE_INFO => -3,
|
2008-08-08 18:19:16 +02:00
|
|
|
|
PE_REDIRECT => -2,
|
|
|
|
|
PE_DONE => -1,
|
|
|
|
|
PE_OK => 0,
|
|
|
|
|
PE_SESSIONEXPIRED => 1,
|
|
|
|
|
PE_FORMEMPTY => 2,
|
|
|
|
|
PE_WRONGMANAGERACCOUNT => 3,
|
|
|
|
|
PE_USERNOTFOUND => 4,
|
|
|
|
|
PE_BADCREDENTIALS => 5,
|
|
|
|
|
PE_LDAPCONNECTFAILED => 6,
|
|
|
|
|
PE_LDAPERROR => 7,
|
|
|
|
|
PE_APACHESESSIONERROR => 8,
|
|
|
|
|
PE_FIRSTACCESS => 9,
|
|
|
|
|
PE_BADCERTIFICATE => 10,
|
|
|
|
|
PE_PP_ACCOUNT_LOCKED => 21,
|
|
|
|
|
PE_PP_PASSWORD_EXPIRED => 22,
|
|
|
|
|
PE_CERTIFICATEREQUIRED => 23,
|
|
|
|
|
PE_ERROR => 24,
|
|
|
|
|
PE_PP_CHANGE_AFTER_RESET => 25,
|
|
|
|
|
PE_PP_PASSWORD_MOD_NOT_ALLOWED => 26,
|
|
|
|
|
PE_PP_MUST_SUPPLY_OLD_PASSWORD => 27,
|
|
|
|
|
PE_PP_INSUFFICIENT_PASSWORD_QUALITY => 28,
|
|
|
|
|
PE_PP_PASSWORD_TOO_SHORT => 29,
|
|
|
|
|
PE_PP_PASSWORD_TOO_YOUNG => 30,
|
|
|
|
|
PE_PP_PASSWORD_IN_HISTORY => 31,
|
2008-09-19 17:28:00 +02:00
|
|
|
|
PE_PP_GRACE => 32,
|
|
|
|
|
PE_PP_EXP_WARNING => 33,
|
|
|
|
|
PE_PASSWORD_MISMATCH => 34,
|
|
|
|
|
PE_PASSWORD_OK => 35,
|
2008-11-24 07:57:18 +01:00
|
|
|
|
PE_NOTIFICATION => 36,
|
2008-12-03 14:27:30 +01:00
|
|
|
|
PE_BADURL => 37,
|
2009-03-08 09:50:58 +01:00
|
|
|
|
PE_NOSCHEME => 38,
|
2009-05-18 15:53:51 +02:00
|
|
|
|
PE_BADOLDPASSWORD => 39,
|
2009-12-19 09:57:59 +01:00
|
|
|
|
PE_MALFORMEDUSER => 40,
|
2010-01-11 15:02:43 +01:00
|
|
|
|
PE_SESSIONNOTGRANTED => 41,
|
2010-01-12 12:05:01 +01:00
|
|
|
|
PE_CONFIRM => 42,
|
2010-01-21 18:38:55 +01:00
|
|
|
|
PE_MAILFORMEMPTY => 43,
|
|
|
|
|
PE_BADMAILTOKEN => 44,
|
|
|
|
|
PE_MAILERROR => 45,
|
|
|
|
|
PE_MAILOK => 46,
|
2010-02-18 18:22:04 +01:00
|
|
|
|
PE_LOGOUT_OK => 47,
|
2010-07-05 17:38:02 +02:00
|
|
|
|
PE_SAML_ERROR => 48,
|
|
|
|
|
PE_SAML_LOAD_SERVICE_ERROR => 49,
|
|
|
|
|
PE_SAML_LOAD_IDP_ERROR => 50,
|
|
|
|
|
PE_SAML_SSO_ERROR => 51,
|
|
|
|
|
PE_SAML_UNKNOWN_ENTITY => 52,
|
|
|
|
|
PE_SAML_DESTINATION_ERROR => 53,
|
|
|
|
|
PE_SAML_CONDITIONS_ERROR => 54,
|
|
|
|
|
PE_SAML_IDPSSOINITIATED_NOTALLOWED => 55,
|
|
|
|
|
PE_SAML_SLO_ERROR => 56,
|
|
|
|
|
PE_SAML_SIGNATURE_ERROR => 57,
|
|
|
|
|
PE_SAML_ART_ERROR => 58,
|
|
|
|
|
PE_SAML_SESSION_ERROR => 59,
|
2010-07-05 17:58:03 +02:00
|
|
|
|
PE_SAML_LOAD_SP_ERROR => 60,
|
|
|
|
|
PE_SAML_ATTR_ERROR => 61,
|
2010-08-27 17:34:03 +02:00
|
|
|
|
PE_OPENID_EMPTY => 62,
|
2010-08-31 17:36:32 +02:00
|
|
|
|
PE_OPENID_BADID => 63,
|
2010-09-29 09:24:56 +02:00
|
|
|
|
PE_MISSINGREQATTR => 64,
|
2010-10-11 14:22:51 +02:00
|
|
|
|
PE_BADPARTNER => 65,
|
2011-05-20 16:30:21 +02:00
|
|
|
|
PE_MAILCONFIRMATION_ALREADY_SENT => 66,
|
2011-07-07 12:35:04 +02:00
|
|
|
|
PE_PASSWORDFORMEMPTY => 67,
|
2011-09-15 11:42:25 +02:00
|
|
|
|
PE_CAS_SERVICE_NOT_ALLOWED => 68,
|
2011-10-28 17:25:36 +02:00
|
|
|
|
PE_MAILFIRSTACCESS => 69,
|
2011-10-28 17:52:19 +02:00
|
|
|
|
PE_MAILNOTFOUND => 70,
|
2011-11-04 16:37:42 +01:00
|
|
|
|
PE_PASSWORDFIRSTACCESS => 71,
|
2011-11-04 17:34:16 +01:00
|
|
|
|
PE_MAILCONFIRMOK => 72,
|
2011-11-17 16:38:01 +01:00
|
|
|
|
PE_RADIUSCONNECTFAILED => 73,
|
2012-02-09 22:56:24 +01:00
|
|
|
|
PE_MUST_SUPPLY_OLD_PASSWORD => 74,
|
2012-02-13 18:35:44 +01:00
|
|
|
|
PE_FORBIDDENIP => 75,
|
2012-07-04 14:33:03 +02:00
|
|
|
|
PE_CAPTCHAERROR => 76,
|
|
|
|
|
PE_CAPTCHAEMPTY => 77,
|
2014-05-26 18:25:33 +02:00
|
|
|
|
PE_REGISTERFIRSTACCESS => 78,
|
|
|
|
|
PE_REGISTERFORMEMPTY => 79,
|
2014-05-27 15:42:00 +02:00
|
|
|
|
PE_REGISTERALREADYEXISTS => 80,
|
2010-01-15 23:01:04 +01:00
|
|
|
|
|
|
|
|
|
# Portal messages
|
|
|
|
|
PM_USER => 0,
|
|
|
|
|
PM_DATE => 1,
|
|
|
|
|
PM_IP => 2,
|
|
|
|
|
PM_SESSIONS_DELETED => 3,
|
|
|
|
|
PM_OTHER_SESSIONS => 4,
|
|
|
|
|
PM_REMOVE_OTHER_SESSIONS => 5,
|
|
|
|
|
PM_PP_GRACE => 6,
|
|
|
|
|
PM_PP_EXP_WARNING => 7,
|
2010-02-04 13:30:18 +01:00
|
|
|
|
PM_SAML_IDPSELECT => 8,
|
|
|
|
|
PM_SAML_IDPCHOOSEN => 9,
|
2010-03-01 21:32:28 +01:00
|
|
|
|
PM_REMEMBERCHOICE => 10,
|
2010-04-23 18:26:23 +02:00
|
|
|
|
PM_SAML_SPLOGOUT => 11,
|
2010-06-01 11:59:37 +02:00
|
|
|
|
PM_REDIRECTION => 12,
|
2010-08-18 15:39:15 +02:00
|
|
|
|
PM_BACKTOSP => 13,
|
2010-08-27 18:07:19 +02:00
|
|
|
|
PM_BACKTOCASURL => 14,
|
2010-08-30 17:46:26 +02:00
|
|
|
|
PM_LOGOUT => 15,
|
2010-09-01 14:56:15 +02:00
|
|
|
|
PM_OPENID_EXCHANGE => 16,
|
2010-09-27 10:40:18 +02:00
|
|
|
|
PM_CDC_WRITER => 17,
|
2010-09-28 18:26:35 +02:00
|
|
|
|
PM_OPENID_RPNS => 18, # OpenID "requested parameter is not set"
|
|
|
|
|
PM_OPENID_PA => 19, # "OpenID policy available at"
|
|
|
|
|
PM_OPENID_AP => 20, # OpenID "Asked parameter"
|
2012-01-19 15:35:23 +01:00
|
|
|
|
PM_ERROR_MSG => 21,
|
2012-02-27 21:16:09 +01:00
|
|
|
|
PM_LAST_LOGINS => 22,
|
|
|
|
|
PM_LAST_FAILED_LOGINS => 23,
|
2015-01-31 15:34:52 +01:00
|
|
|
|
PM_OIDC_CONSENT => 24,
|
2015-03-11 15:34:31 +01:00
|
|
|
|
PM_OIDC_SCOPE_OPENID => 25,
|
|
|
|
|
PM_OIDC_SCOPE_PROFILE => 26,
|
|
|
|
|
PM_OIDC_SCOPE_EMAIL => 27,
|
|
|
|
|
PM_OIDC_SCOPE_ADDRESS => 28,
|
|
|
|
|
PM_OIDC_SCOPE_PHONE => 29,
|
|
|
|
|
PM_OIDC_SCOPE_OTHER => 30,
|
2015-04-03 11:05:36 +02:00
|
|
|
|
PM_OIDC_CONFIRM_LOGOUT => 31,
|
2008-05-30 08:07:37 +02:00
|
|
|
|
};
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2007-01-11 07:42:57 +01:00
|
|
|
|
# EXPORTER PARAMETERS
|
2010-04-29 15:47:57 +02:00
|
|
|
|
our @EXPORT = qw( PE_IMG_NOK PE_IMG_OK PE_INFO PE_REDIRECT PE_DONE PE_OK
|
2010-04-29 15:39:26 +02:00
|
|
|
|
PE_SESSIONEXPIRED PE_FORMEMPTY PE_WRONGMANAGERACCOUNT PE_USERNOTFOUND
|
|
|
|
|
PE_BADCREDENTIALS PE_LDAPCONNECTFAILED PE_LDAPERROR PE_APACHESESSIONERROR
|
|
|
|
|
PE_FIRSTACCESS PE_BADCERTIFICATE PE_PP_ACCOUNT_LOCKED PE_PP_PASSWORD_EXPIRED
|
2010-01-11 17:04:36 +01:00
|
|
|
|
PE_CERTIFICATEREQUIRED PE_ERROR PE_PP_CHANGE_AFTER_RESET
|
|
|
|
|
PE_PP_PASSWORD_MOD_NOT_ALLOWED PE_PP_MUST_SUPPLY_OLD_PASSWORD
|
|
|
|
|
PE_PP_INSUFFICIENT_PASSWORD_QUALITY PE_PP_PASSWORD_TOO_SHORT
|
|
|
|
|
PE_PP_PASSWORD_TOO_YOUNG PE_PP_PASSWORD_IN_HISTORY PE_PP_GRACE
|
|
|
|
|
PE_PP_EXP_WARNING PE_PASSWORD_MISMATCH PE_PASSWORD_OK PE_NOTIFICATION
|
2010-01-11 17:58:57 +01:00
|
|
|
|
PE_BADURL PE_NOSCHEME PE_BADOLDPASSWORD PE_MALFORMEDUSER PE_SESSIONNOTGRANTED
|
2010-01-21 18:38:55 +01:00
|
|
|
|
PE_CONFIRM PE_MAILFORMEMPTY PE_BADMAILTOKEN PE_MAILERROR PE_MAILOK
|
2010-07-05 17:38:02 +02:00
|
|
|
|
PE_LOGOUT_OK PE_SAML_ERROR PE_SAML_LOAD_SERVICE_ERROR PE_SAML_LOAD_IDP_ERROR
|
|
|
|
|
PE_SAML_SSO_ERROR PE_SAML_UNKNOWN_ENTITY PE_SAML_DESTINATION_ERROR
|
|
|
|
|
PE_SAML_CONDITIONS_ERROR PE_SAML_IDPSSOINITIATED_NOTALLOWED PE_SAML_SLO_ERROR
|
|
|
|
|
PE_SAML_SIGNATURE_ERROR PE_SAML_ART_ERROR PE_SAML_SESSION_ERROR
|
2010-08-31 17:36:32 +02:00
|
|
|
|
PE_SAML_LOAD_SP_ERROR PE_SAML_ATTR_ERROR PE_OPENID_EMPTY PE_OPENID_BADID
|
2011-05-20 16:30:21 +02:00
|
|
|
|
PE_MISSINGREQATTR PE_BADPARTNER PE_MAILCONFIRMATION_ALREADY_SENT
|
2011-10-28 17:25:36 +02:00
|
|
|
|
PE_PASSWORDFORMEMPTY PE_CAS_SERVICE_NOT_ALLOWED PE_MAILFIRSTACCESS
|
2011-11-04 17:34:16 +01:00
|
|
|
|
PE_MAILNOTFOUND PE_PASSWORDFIRSTACCESS PE_MAILCONFIRMOK
|
2012-07-04 14:33:03 +02:00
|
|
|
|
PE_MUST_SUPPLY_OLD_PASSWORD PE_FORBIDDENIP PE_CAPTCHAERROR PE_CAPTCHAEMPTY
|
2014-05-27 15:42:00 +02:00
|
|
|
|
PE_REGISTERFIRSTACCESS PE_REGISTERFORMEMPTY PE_REGISTERALREADYEXISTS
|
2010-01-21 18:38:55 +01:00
|
|
|
|
PM_USER PM_DATE PM_IP PM_SESSIONS_DELETED PM_OTHER_SESSIONS
|
2010-01-15 23:01:04 +01:00
|
|
|
|
PM_REMOVE_OTHER_SESSIONS PM_PP_GRACE PM_PP_EXP_WARNING
|
2010-04-26 17:39:38 +02:00
|
|
|
|
PM_SAML_IDPSELECT PM_SAML_IDPCHOOSEN PM_REMEMBERCHOICE PM_SAML_SPLOGOUT
|
2010-09-01 14:56:15 +02:00
|
|
|
|
PM_REDIRECTION PM_BACKTOSP PM_BACKTOCASURL PM_LOGOUT PM_OPENID_EXCHANGE
|
2012-01-19 15:35:23 +01:00
|
|
|
|
PM_CDC_WRITER PM_OPENID_RPNS PM_OPENID_PA PM_OPENID_AP PM_ERROR_MSG
|
2015-03-11 15:34:31 +01:00
|
|
|
|
PM_LAST_LOGINS PM_LAST_FAILED_LOGINS PM_OIDC_CONSENT PM_OIDC_SCOPE_OPENID
|
|
|
|
|
PM_OIDC_SCOPE_PROFILE PM_OIDC_SCOPE_EMAIL PM_OIDC_SCOPE_ADDRESS
|
2015-04-03 11:05:36 +02:00
|
|
|
|
PM_OIDC_SCOPE_PHONE PM_OIDC_SCOPE_OTHER PM_OIDC_CONFIRM_LOGOUT
|
2010-01-11 17:04:36 +01:00
|
|
|
|
);
|
2008-05-25 14:54:45 +02:00
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ @EXPORT, 'import' ], );
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
|
|
|
|
|
|
2011-02-07 11:27:36 +01:00
|
|
|
|
# Share secure jail between threads
|
2008-12-11 18:02:02 +01:00
|
|
|
|
our $safe;
|
2008-11-20 19:13:27 +01:00
|
|
|
|
|
2010-10-30 21:25:38 +02:00
|
|
|
|
BEGIN {
|
|
|
|
|
eval {
|
|
|
|
|
require threads::shared;
|
|
|
|
|
threads::shared::share($safe);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-29 11:28:31 +01:00
|
|
|
|
##@cmethod Lemonldap::NG::Portal::Simple new(hashRef args)
|
2008-12-03 14:27:30 +01:00
|
|
|
|
# Class constructor.
|
2008-12-26 18:58:48 +01:00
|
|
|
|
#@param args hash reference
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal::Simple object
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub new {
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2010-02-26 11:53:43 +01:00
|
|
|
|
@ISA = qw(Lemonldap::NG::Common::CGI Exporter);
|
2008-12-06 08:27:35 +01:00
|
|
|
|
binmode( STDOUT, ":utf8" );
|
2006-12-18 12:32:33 +01:00
|
|
|
|
my $class = shift;
|
2008-12-07 15:12:36 +01:00
|
|
|
|
return $class if ( ref($class) );
|
2013-10-21 23:24:03 +02:00
|
|
|
|
my $self = $class->SUPER::new() or return undef;
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
|
|
|
|
# Reinit _url
|
2009-04-11 13:16:44 +02:00
|
|
|
|
$self->{_url} = '';
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
|
|
|
|
# Get global configuration
|
2008-11-21 18:51:52 +01:00
|
|
|
|
$self->getConf(@_)
|
|
|
|
|
or $self->abort( "Configuration error",
|
|
|
|
|
"Unable to get configuration: $Lemonldap::NG::Common::Conf::msg" );
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2015-12-16 21:44:27 +01:00
|
|
|
|
$self->{multiValuesSeparator} ||= ';';
|
|
|
|
|
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Test mandatory elements
|
2010-10-18 17:33:21 +02:00
|
|
|
|
|
|
|
|
|
# 1. Sessions backend
|
2008-11-21 18:51:52 +01:00
|
|
|
|
$self->abort( "Configuration error",
|
|
|
|
|
"You've to indicate a an Apache::Session storage module !" )
|
2006-12-18 12:32:33 +01:00
|
|
|
|
unless ( $self->{globalStorage} );
|
2014-02-26 11:57:49 +01:00
|
|
|
|
|
2014-02-26 18:10:39 +01:00
|
|
|
|
# Use global storage for all backends by default
|
2014-02-26 11:57:49 +01:00
|
|
|
|
|
|
|
|
|
# Persistent
|
|
|
|
|
$self->{persistentStorage} ||= $self->{globalStorage};
|
|
|
|
|
if ( !$self->{persistentStorageOptions}
|
|
|
|
|
or !%{ $self->{persistentStorageOptions} } )
|
|
|
|
|
{
|
2011-06-10 14:20:49 +02:00
|
|
|
|
$self->{persistentStorageOptions} = $self->{globalStorageOptions};
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-14 10:00:12 +01:00
|
|
|
|
# SAML
|
|
|
|
|
$self->{samlStorage} ||= $self->{globalStorage};
|
|
|
|
|
if ( !$self->{samlStorageOptions} or !%{ $self->{samlStorageOptions} } ) {
|
|
|
|
|
$self->{samlStorageOptions} = $self->{globalStorageOptions};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# CAS
|
|
|
|
|
$self->{casStorage} ||= $self->{globalStorage};
|
|
|
|
|
if ( !$self->{casStorageOptions} or !%{ $self->{casStorageOptions} } ) {
|
|
|
|
|
$self->{casStorageOptions} = $self->{globalStorageOptions};
|
|
|
|
|
}
|
2010-10-20 07:47:10 +02:00
|
|
|
|
|
2014-06-10 18:21:33 +02:00
|
|
|
|
# Captcha
|
|
|
|
|
$self->{captchaStorage} ||= $self->{globalStorage};
|
|
|
|
|
if ( !$self->{captchaStorageOptions}
|
|
|
|
|
or !%{ $self->{captchaStorageOptions} } )
|
|
|
|
|
{
|
|
|
|
|
$self->{captchaStorageOptions} = $self->{globalStorageOptions};
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-11 12:39:20 +01:00
|
|
|
|
# OpenIDConnect
|
|
|
|
|
$self->{oidcStorage} ||= $self->{globalStorage};
|
|
|
|
|
if ( !$self->{oidcStorageOptions} or !%{ $self->{oidcStorageOptions} } ) {
|
2015-06-12 09:51:37 +02:00
|
|
|
|
$self->{oidcStorageOptions} = $self->{globalStorageOptions};
|
2015-03-11 12:39:20 +01:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-18 17:33:21 +02:00
|
|
|
|
# 2. Domain
|
2008-11-21 18:51:52 +01:00
|
|
|
|
$self->abort( "Configuration error",
|
|
|
|
|
"You've to indicate a domain for cookies" )
|
|
|
|
|
unless ( $self->{domain} );
|
2006-12-18 12:32:33 +01:00
|
|
|
|
$self->{domain} =~ s/^([^\.])/.$1/;
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2010-09-28 12:30:57 +02:00
|
|
|
|
# Load Display and Menu functions
|
2010-09-27 16:18:48 +02:00
|
|
|
|
$self->loadModule('Lemonldap::NG::Portal::Menu');
|
2010-09-28 12:30:57 +02:00
|
|
|
|
$self->loadModule('Lemonldap::NG::Portal::Display');
|
2010-09-27 16:18:48 +02:00
|
|
|
|
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Rules to allow redirection
|
2012-06-12 17:46:18 +02:00
|
|
|
|
$self->{mustRedirect} =
|
|
|
|
|
defined $ENV{REQUEST_METHOD}
|
|
|
|
|
? ( $ENV{REQUEST_METHOD} eq "POST" and not $self->param('newpassword') )
|
|
|
|
|
: $self->param('logout') ? 1
|
|
|
|
|
: 0;
|
2008-06-06 05:51:39 +02:00
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# Push authentication/userDB/passwordDB modules in @ISA
|
2014-05-28 18:23:23 +02:00
|
|
|
|
foreach my $type (qw(authentication userDB passwordDB registerDB)) {
|
2009-12-10 18:03:57 +01:00
|
|
|
|
my $module_name = 'Lemonldap::NG::Portal::';
|
2010-07-21 14:13:12 +02:00
|
|
|
|
my $db_type = $type;
|
2015-03-09 16:55:46 +01:00
|
|
|
|
my $db_name = $self->{$db_type}
|
|
|
|
|
or $self->abort("'$db_type' is not set");
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
|
|
|
|
# Adapt module type to real module name
|
|
|
|
|
$db_type =~ s/authentication/Auth/;
|
|
|
|
|
$db_type =~ s/userDB/UserDB/;
|
|
|
|
|
$db_type =~ s/passwordDB/PasswordDB/;
|
2014-05-28 18:23:23 +02:00
|
|
|
|
$db_type =~ s/registerDB/RegisterDB/;
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
|
|
|
|
# Full module name
|
|
|
|
|
$module_name .= $db_type . $db_name;
|
|
|
|
|
|
|
|
|
|
# Remove white spaces
|
|
|
|
|
$module_name =~ s/\s.*$//;
|
|
|
|
|
|
|
|
|
|
# Try to load module
|
2010-01-28 15:47:51 +01:00
|
|
|
|
$self->abort( "Configuration error", "Unable to load $module_name" )
|
|
|
|
|
unless $self->loadModule($module_name);
|
2008-10-05 20:42:50 +02:00
|
|
|
|
|
|
|
|
|
# $self->{authentication} and $self->{userDB} can contains arguments
|
|
|
|
|
# (key1 = scalar_value; key2 = ...)
|
2009-12-10 18:03:57 +01:00
|
|
|
|
unless ( $db_name =~ /^Multi/ ) {
|
|
|
|
|
$db_name =~ s/^\w+\s*//;
|
|
|
|
|
my %h = split( /\s*[=;]\s*/, $db_name ) if ($db_name);
|
2009-03-08 09:50:58 +01:00
|
|
|
|
%$self = ( %h, %$self );
|
|
|
|
|
}
|
2008-10-05 20:42:50 +02:00
|
|
|
|
}
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# Check issuerDB path to load the correct issuerDB module
|
2014-11-14 15:29:55 +01:00
|
|
|
|
foreach my $issuerDBtype (qw(SAML OpenID CAS OpenIDConnect)) {
|
2010-08-23 15:27:16 +02:00
|
|
|
|
my $module_name = 'Lemonldap::NG::Portal::IssuerDB' . $issuerDBtype;
|
|
|
|
|
|
|
|
|
|
$self->lmLog( "[IssuerDB activation] Try issuerDB module $issuerDBtype",
|
|
|
|
|
'debug' );
|
|
|
|
|
|
2010-08-27 15:01:54 +02:00
|
|
|
|
# Check activation flag
|
|
|
|
|
my $activation =
|
|
|
|
|
$self->{ "issuerDB" . $issuerDBtype . "Activation" } ||= "0";
|
|
|
|
|
|
|
|
|
|
unless ($activation) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"[IssuerDB activation] Activation flag set to off, trying next",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# Check the path
|
|
|
|
|
my $path = $self->{ "issuerDB" . $issuerDBtype . "Path" };
|
|
|
|
|
if ( defined $path ) {
|
|
|
|
|
$self->lmLog( "[IssuerDB activation] Found path $path", 'debug' );
|
|
|
|
|
|
|
|
|
|
# Get current path
|
|
|
|
|
my $url_path = $self->url( -absolute => 1 );
|
2010-08-31 17:14:44 +02:00
|
|
|
|
$url_path =~ s#^//#/#;
|
2010-08-23 15:27:16 +02:00
|
|
|
|
$self->lmLog(
|
|
|
|
|
"[IssuerDB activation] Path of current request is $url_path",
|
|
|
|
|
'debug' );
|
|
|
|
|
|
|
|
|
|
# Match regular expression
|
|
|
|
|
if ( $url_path =~ m#$path# ) {
|
|
|
|
|
$self->abort( "Configuration error",
|
|
|
|
|
"Unable to load $module_name" )
|
|
|
|
|
unless $self->loadModule($module_name);
|
|
|
|
|
|
|
|
|
|
# Remember loaded module
|
|
|
|
|
$self->{_activeIssuerDB} = $issuerDBtype;
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"[IssuerDB activation] IssuerDB module $issuerDBtype loaded",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
last;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"[IssuerDB activation] Path do not match, trying next",
|
|
|
|
|
'debug' );
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->lmLog( "[IssuerDB activation] No path defined", 'debug' );
|
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Load default issuerDB module if none was choosed
|
|
|
|
|
unless ( $self->{_activeIssuerDB} ) {
|
|
|
|
|
|
|
|
|
|
# Manage old configuration format
|
|
|
|
|
my $db_type = $self->{'issuerDB'} || 'Null';
|
|
|
|
|
|
|
|
|
|
my $module_name = 'Lemonldap::NG::Portal::IssuerDB' . $db_type;
|
|
|
|
|
|
|
|
|
|
$self->abort( "Configuration error", "Unable to load $module_name" )
|
|
|
|
|
unless $self->loadModule($module_name);
|
|
|
|
|
|
|
|
|
|
# Remember loaded module
|
|
|
|
|
$self->{_activeIssuerDB} = $db_type;
|
|
|
|
|
$self->lmLog( "[IssuerDB activation] IssuerDB module $db_type loaded",
|
|
|
|
|
'debug' );
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Notifications
|
2008-11-24 07:57:18 +01:00
|
|
|
|
if ( $self->{notification} ) {
|
2012-07-12 23:04:06 +02:00
|
|
|
|
require Lemonldap::NG::Common::Notification;
|
2009-01-30 16:26:34 +01:00
|
|
|
|
my $tmp;
|
2011-06-08 12:02:38 +02:00
|
|
|
|
|
|
|
|
|
# Use configuration options
|
2009-01-30 16:26:34 +01:00
|
|
|
|
if ( $self->{notificationStorage} ) {
|
2011-06-08 10:06:17 +02:00
|
|
|
|
$tmp->{type} = $self->{notificationStorage};
|
|
|
|
|
foreach ( keys %{ $self->{notificationStorageOptions} } ) {
|
|
|
|
|
$tmp->{$_} = $self->{notificationStorageOptions}->{$_};
|
|
|
|
|
}
|
2009-01-30 16:26:34 +01:00
|
|
|
|
}
|
2011-06-08 12:02:38 +02:00
|
|
|
|
|
|
|
|
|
# Else use the configuration backend
|
2009-01-30 16:26:34 +01:00
|
|
|
|
else {
|
2009-02-11 17:18:38 +01:00
|
|
|
|
(%$tmp) = ( %{ $self->{lmConf} } );
|
2009-01-30 16:26:34 +01:00
|
|
|
|
$self->abort( "notificationStorage not defined",
|
|
|
|
|
"This parameter is required to use notification system" )
|
|
|
|
|
unless ( ref($tmp) );
|
2011-06-08 12:02:38 +02:00
|
|
|
|
|
|
|
|
|
# Get the type
|
2009-02-11 17:18:38 +01:00
|
|
|
|
$tmp->{type} =~ s/.*:://;
|
2012-08-29 15:43:43 +02:00
|
|
|
|
$tmp->{type} =~ s/(CDBI|RDBI)/DBI/; # CDBI/RDBI are DBI
|
2011-06-08 12:02:38 +02:00
|
|
|
|
|
2013-10-22 18:26:20 +02:00
|
|
|
|
# If type not File, DBI or LDAP, abort
|
|
|
|
|
$self->abort("Only File, DBI or LDAP supported for Notifications")
|
|
|
|
|
unless $tmp->{type} =~ /^(File|DBI|LDAP)$/;
|
2011-06-08 12:02:38 +02:00
|
|
|
|
|
|
|
|
|
# Force table name
|
2009-01-30 16:26:34 +01:00
|
|
|
|
$tmp->{table} = 'notifications';
|
|
|
|
|
}
|
2011-06-08 12:02:38 +02:00
|
|
|
|
|
2009-02-12 20:48:53 +01:00
|
|
|
|
$tmp->{p} = $self;
|
2012-07-12 23:04:06 +02:00
|
|
|
|
$self->{notifObject} = Lemonldap::NG::Common::Notification->new($tmp);
|
|
|
|
|
$self->abort($Lemonldap::NG::Common::Notification::msg)
|
2009-01-30 16:26:34 +01:00
|
|
|
|
unless ( $self->{notifObject} );
|
2008-11-24 07:57:18 +01:00
|
|
|
|
}
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
|
|
|
|
# SOAP
|
2009-02-24 18:53:59 +01:00
|
|
|
|
if ( $self->{Soap} or $self->{soap} ) {
|
2011-07-20 10:41:09 +02:00
|
|
|
|
$self->loadModule('Lemonldap::NG::Portal::_SOAP');
|
2011-06-08 11:27:02 +02:00
|
|
|
|
if ( $self->{notification} and $ENV{PATH_INFO} ) {
|
2011-07-20 10:41:09 +02:00
|
|
|
|
$self->{CustomSOAPServices} ||= {};
|
2012-09-08 12:55:55 +02:00
|
|
|
|
$self->{CustomSOAPServices}->{'/notification'} = {
|
|
|
|
|
f => 'newNotification deleteNotification',
|
|
|
|
|
o => $self->{notifObject}
|
|
|
|
|
};
|
2010-01-11 17:04:36 +01:00
|
|
|
|
}
|
2009-02-24 18:53:59 +01:00
|
|
|
|
$self->startSoapServices();
|
2008-12-07 15:12:36 +01:00
|
|
|
|
}
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
|
|
|
|
# Trusted domains
|
2012-05-23 20:46:38 +02:00
|
|
|
|
$self->{trustedDomains} ||= "";
|
2012-06-12 17:46:18 +02:00
|
|
|
|
$self->{trustedDomains} = "*"
|
|
|
|
|
if ( $self->{trustedDomains} =~ /(^|\s)\*(\s|$)/ );
|
2012-05-23 20:46:38 +02:00
|
|
|
|
if ( $self->{trustedDomains} and $self->{trustedDomains} ne "*" ) {
|
2013-02-08 14:32:22 +01:00
|
|
|
|
$self->{trustedDomains} =~ s#(^|\s+)\.#${1}[^/]+.#g;
|
2012-06-12 17:46:18 +02:00
|
|
|
|
$self->{trustedDomains} =
|
|
|
|
|
'(' . join( '|', split( /\s+/, $self->{trustedDomains} ) ) . ')';
|
2012-05-23 20:46:38 +02:00
|
|
|
|
$self->{trustedDomains} =~ s/\./\\./g;
|
2009-06-14 18:43:02 +02:00
|
|
|
|
}
|
2012-07-26 04:47:27 +02:00
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
return $self;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-01 14:50:48 +02:00
|
|
|
|
##@method boolean loadModule(string module, boolean ignoreError)
|
2010-01-28 15:47:51 +01:00
|
|
|
|
# Load a module into portal namespace
|
|
|
|
|
# @param module module name
|
2013-10-01 14:50:48 +02:00
|
|
|
|
# @param ignoreError set to 1 if error should not appear in logs
|
2010-01-28 15:47:51 +01:00
|
|
|
|
# @return boolean
|
|
|
|
|
sub loadModule {
|
2013-10-01 14:50:48 +02:00
|
|
|
|
my ( $self, $module, $ignoreError ) = splice @_;
|
2010-01-28 15:47:51 +01:00
|
|
|
|
|
|
|
|
|
return 1 unless $module;
|
|
|
|
|
|
|
|
|
|
# Load module test
|
|
|
|
|
eval "require $module";
|
|
|
|
|
if ($@) {
|
2013-10-01 14:50:48 +02:00
|
|
|
|
$self->lmLog( "$module load error: $@", 'error' ) unless $ignoreError;
|
2010-01-28 15:47:51 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Push module in @ISA
|
|
|
|
|
push @ISA, $module;
|
2010-09-02 17:32:40 +02:00
|
|
|
|
|
|
|
|
|
$self->lmLog( "Module $module loaded", 'debug' );
|
|
|
|
|
|
2010-01-28 15:47:51 +01:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-29 11:28:31 +01:00
|
|
|
|
##@method protected boolean getConf(hashRef args)
|
2008-12-03 14:27:30 +01:00
|
|
|
|
# Copy all parameters in caller object.
|
2008-12-26 18:58:48 +01:00
|
|
|
|
#@param args hash-ref
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return True
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub getConf {
|
|
|
|
|
my ($self) = shift;
|
|
|
|
|
my %args;
|
|
|
|
|
if ( ref( $_[0] ) ) {
|
|
|
|
|
%args = %{ $_[0] };
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
%args = @_;
|
|
|
|
|
}
|
|
|
|
|
%$self = ( %$self, %args );
|
|
|
|
|
1;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-20 12:31:20 +02:00
|
|
|
|
## @method protected void setHiddenFormValue(string fieldname, string value, string prefix, boolean base64)
|
2010-04-02 11:17:02 +02:00
|
|
|
|
# Add element into $self->{portalHiddenFormValues}, those values could be
|
|
|
|
|
# used to hide values into HTML form.
|
2010-08-20 12:31:20 +02:00
|
|
|
|
# @param fieldname The field name which will contain the correponding value
|
|
|
|
|
# @param value The associated value
|
|
|
|
|
# @param prefix Prefix of the field key
|
|
|
|
|
# @param base64 Encode value in base64
|
|
|
|
|
# @return nothing
|
2010-04-02 11:17:02 +02:00
|
|
|
|
sub setHiddenFormValue {
|
2010-08-20 12:31:20 +02:00
|
|
|
|
my ( $self, $key, $val, $prefix, $base64 ) = splice @_;
|
|
|
|
|
|
|
|
|
|
# Default values
|
|
|
|
|
$prefix = "lmhidden_" unless defined $prefix;
|
|
|
|
|
$base64 = 1 unless defined $base64;
|
|
|
|
|
|
|
|
|
|
# Store value
|
2010-04-09 15:27:54 +02:00
|
|
|
|
if ($val) {
|
2010-08-20 12:31:20 +02:00
|
|
|
|
$key = $prefix . $key;
|
|
|
|
|
$val = encode_base64($val) if $base64;
|
|
|
|
|
$self->{portalHiddenFormValues}->{$key} = $val;
|
2015-01-29 14:32:31 +01:00
|
|
|
|
$self->lmLog( "Store $val in hidden key $key", 'debug' );
|
2010-04-02 17:28:29 +02:00
|
|
|
|
}
|
2010-04-02 11:17:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-20 12:31:20 +02:00
|
|
|
|
## @method public void getHiddenFormValue(string fieldname, string prefix, boolean base64)
|
2010-04-02 11:17:02 +02:00
|
|
|
|
# Get value into $self->{portalHiddenFormValues}.
|
2010-08-20 12:31:20 +02:00
|
|
|
|
# @param fieldname The existing field name which contains a value
|
|
|
|
|
# @param prefix Prefix of the field key
|
|
|
|
|
# @param base64 Decode value from base64
|
|
|
|
|
# @return string The associated value
|
2010-04-02 11:17:02 +02:00
|
|
|
|
sub getHiddenFormValue {
|
2010-08-20 12:31:20 +02:00
|
|
|
|
my ( $self, $key, $prefix, $base64 ) = splice @_;
|
|
|
|
|
|
|
|
|
|
# Default values
|
|
|
|
|
$prefix = "lmhidden_" unless defined $prefix;
|
|
|
|
|
$base64 = 1 unless defined $base64;
|
|
|
|
|
|
|
|
|
|
$key = $prefix . $key;
|
|
|
|
|
|
|
|
|
|
# Get value
|
2010-04-09 15:27:54 +02:00
|
|
|
|
if ( my $val = $self->param($key) ) {
|
2010-08-20 12:31:20 +02:00
|
|
|
|
$val = decode_base64($val) if $base64;
|
|
|
|
|
return $val;
|
2015-01-29 14:32:31 +01:00
|
|
|
|
$self->lmLog( "Hidden value $val found for key $key", 'debug' );
|
2010-04-02 17:28:29 +02:00
|
|
|
|
}
|
2010-08-20 12:31:20 +02:00
|
|
|
|
|
|
|
|
|
# No value found
|
2010-04-02 17:28:29 +02:00
|
|
|
|
return undef;
|
2010-04-02 11:17:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-20 12:31:20 +02:00
|
|
|
|
## @method protected void clearHiddenFormValue(arrayref keys)
|
|
|
|
|
# Clear values form stored hidden fields
|
|
|
|
|
# Delete all keys if no keys provided
|
|
|
|
|
# @param keys Array reference of keys
|
|
|
|
|
# @return nothing
|
2010-08-20 12:52:52 +02:00
|
|
|
|
sub clearHiddenFormValue {
|
2010-08-20 12:31:20 +02:00
|
|
|
|
my ( $self, $keys ) = splice @_;
|
|
|
|
|
|
|
|
|
|
unless ( defined $keys ) {
|
|
|
|
|
delete $self->{portalHiddenFormValues};
|
2015-01-29 14:32:31 +01:00
|
|
|
|
$self->lmLog( "Delete all hidden values", 'debug' );
|
2010-08-20 12:31:20 +02:00
|
|
|
|
}
|
|
|
|
|
else {
|
2015-01-29 14:32:31 +01:00
|
|
|
|
foreach (@$keys) {
|
|
|
|
|
delete $self->{portalHiddenFormValues}->{$_};
|
|
|
|
|
$self->lmLog( "Delete hidden value for key $_", 'debug' );
|
|
|
|
|
}
|
2010-08-20 12:31:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-02 11:17:02 +02:00
|
|
|
|
##@method public string buildHiddenForm()
|
|
|
|
|
# Return an HTML representation of hidden values.
|
2010-08-20 12:31:20 +02:00
|
|
|
|
# @return HTML code
|
2010-04-02 11:17:02 +02:00
|
|
|
|
sub buildHiddenForm {
|
|
|
|
|
my $self = shift;
|
2010-04-09 15:27:54 +02:00
|
|
|
|
my @keys = keys %{ $self->{portalHiddenFormValues} };
|
2010-04-14 17:37:57 +02:00
|
|
|
|
my $val = '';
|
2010-08-20 12:31:20 +02:00
|
|
|
|
|
2010-04-09 15:27:54 +02:00
|
|
|
|
foreach (@keys) {
|
2010-08-20 12:31:20 +02:00
|
|
|
|
|
|
|
|
|
# Check XSS attacks
|
2010-09-03 16:15:44 +02:00
|
|
|
|
next
|
|
|
|
|
if $self->checkXSSAttack( $_, $self->{portalHiddenFormValues}->{$_} );
|
2010-08-20 12:31:20 +02:00
|
|
|
|
|
|
|
|
|
# Build hidden input HTML code
|
2013-10-22 18:48:02 +02:00
|
|
|
|
$val .= qq{<input type="hidden" name="$_" id="$_" value="}
|
2010-04-09 15:27:54 +02:00
|
|
|
|
. $self->{portalHiddenFormValues}->{$_} . '" />';
|
2010-04-02 11:17:02 +02:00
|
|
|
|
}
|
2010-08-20 12:31:20 +02:00
|
|
|
|
|
2010-04-02 11:17:02 +02:00
|
|
|
|
return $val;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-25 10:57:53 +02:00
|
|
|
|
## @method void initCaptcha(void)
|
2012-07-04 14:33:03 +02:00
|
|
|
|
# init captcha module and generate captcha
|
2012-07-25 10:57:53 +02:00
|
|
|
|
# @return nothing
|
2012-07-04 14:33:03 +02:00
|
|
|
|
sub initCaptcha {
|
|
|
|
|
my $self = shift;
|
2012-09-08 12:55:55 +02:00
|
|
|
|
|
2014-06-10 18:21:33 +02:00
|
|
|
|
# Create new captcha
|
|
|
|
|
my $captcha = Lemonldap::NG::Common::Captcha->new(
|
|
|
|
|
{
|
|
|
|
|
storageModule => $self->{captchaStorage},
|
|
|
|
|
storageModuleOptions => $self->{captchaStorageOptions},
|
|
|
|
|
size => $self->{captcha_size},
|
|
|
|
|
}
|
2012-07-26 04:47:27 +02:00
|
|
|
|
);
|
2012-08-31 09:53:40 +02:00
|
|
|
|
|
2014-06-10 18:21:33 +02:00
|
|
|
|
$self->{captcha_secret} = $captcha->code;
|
2014-06-11 12:22:34 +02:00
|
|
|
|
$self->{captcha_code} = $captcha->md5;
|
2014-06-10 18:21:33 +02:00
|
|
|
|
$self->{captcha_img} = $self->{portal} . "?displayCaptcha=" . $captcha->md5;
|
2012-08-31 09:53:40 +02:00
|
|
|
|
|
2013-02-20 17:04:29 +01:00
|
|
|
|
$self->lmLog( "Captcha code generated: " . $self->{captcha_code}, 'debug' );
|
|
|
|
|
|
|
|
|
|
return;
|
2012-07-04 14:33:03 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-10 18:21:33 +02:00
|
|
|
|
## @method int checkCaptcha(code, ccode)
|
|
|
|
|
# Check captcha auth
|
|
|
|
|
# @param code that user enter in the form
|
|
|
|
|
# @param captcha code generated by Authen::Captcha
|
|
|
|
|
# @return a constant
|
|
|
|
|
sub checkCaptcha {
|
|
|
|
|
my ( $self, $code, $ccode ) = splice @_;
|
|
|
|
|
|
2014-06-11 12:22:34 +02:00
|
|
|
|
# Get captcha object
|
2014-06-10 18:21:33 +02:00
|
|
|
|
my $captcha = Lemonldap::NG::Common::Captcha->new(
|
|
|
|
|
{
|
|
|
|
|
storageModule => $self->{captchaStorage},
|
|
|
|
|
storageModuleOptions => $self->{captchaStorageOptions},
|
|
|
|
|
md5 => $ccode,
|
|
|
|
|
size => $self->{captcha_size},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2014-06-11 12:22:34 +02:00
|
|
|
|
# Check code
|
2014-06-10 18:21:33 +02:00
|
|
|
|
if ( $captcha && $captcha->code ) {
|
|
|
|
|
|
|
|
|
|
if ( $code eq $captcha->code ) {
|
|
|
|
|
$self->lmLog( "Code $code match captcha $ccode", 'debug' );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return -2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-09 17:44:19 +01:00
|
|
|
|
## @method int removeCaptcha(ccode)
|
|
|
|
|
# Remove captcha session
|
|
|
|
|
# @param captcha code generated by Authen::Captcha
|
|
|
|
|
# @return a constant
|
|
|
|
|
sub removeCaptcha {
|
|
|
|
|
my ( $self, $ccode ) = splice @_;
|
|
|
|
|
|
|
|
|
|
# Get captcha object
|
|
|
|
|
my $captcha = Lemonldap::NG::Common::Captcha->new(
|
|
|
|
|
{
|
|
|
|
|
storageModule => $self->{captchaStorage},
|
|
|
|
|
storageModuleOptions => $self->{captchaStorageOptions},
|
|
|
|
|
md5 => $ccode,
|
|
|
|
|
size => $self->{captcha_size},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
# Remove captcha session (will not be used anymore)
|
|
|
|
|
if ( $captcha->removeSession ) {
|
|
|
|
|
$self->lmLog( "Captcha session $ccode removed", 'debug' );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->lmLog( "Unable to remove captcha session $ccode", 'warn' );
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-23 20:46:38 +02:00
|
|
|
|
## @method boolean isTrustedUrl(string url)
|
|
|
|
|
# Check if an URL's domain name is declared in LL::NG config or is declared as trusted domain
|
|
|
|
|
# @param url Parameter url
|
|
|
|
|
# @param value Parameter value
|
|
|
|
|
# @return 1 if url can be trusted, 0 else
|
|
|
|
|
sub isTrustedUrl {
|
|
|
|
|
my ( $self, $url ) = splice @_;
|
|
|
|
|
return
|
2012-06-12 17:46:18 +02:00
|
|
|
|
$url =~ m#^https?://$self->{reVHosts}(:\d+)?/#o
|
|
|
|
|
|| $self->{trustedDomains} eq "*"
|
|
|
|
|
|| $self->{trustedDomains}
|
|
|
|
|
&& $url =~ m#^https?://$self->{trustedDomains}(:\d+)?/#o;
|
2012-05-23 20:46:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-03 16:15:44 +02:00
|
|
|
|
## @method boolean checkXSSAttack(string name, string value)
|
|
|
|
|
# Check value to detect XSS attack
|
|
|
|
|
# @param name Parameter name
|
|
|
|
|
# @param value Parameter value
|
|
|
|
|
# @return 1 if attack detected, 0 else
|
|
|
|
|
sub checkXSSAttack {
|
|
|
|
|
my ( $self, $name, $value ) = splice @_;
|
|
|
|
|
|
2011-05-30 17:34:43 +02:00
|
|
|
|
# Empty values are not bad
|
|
|
|
|
return 0 unless $value;
|
|
|
|
|
|
|
|
|
|
# Test value
|
2010-09-03 16:15:44 +02:00
|
|
|
|
if ( $value =~ m/(?:\0|<|'|"|`|\%(?:00|25|3C|22|27|2C))/ ) {
|
|
|
|
|
$self->lmLog( "XSS attack detected (param: $name | value: $value)",
|
|
|
|
|
"warn" );
|
2012-02-27 22:27:52 +01:00
|
|
|
|
return $self->{checkXSS};
|
2010-09-03 16:15:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-01 16:38:06 +01:00
|
|
|
|
=begin WSDL
|
|
|
|
|
|
|
|
|
|
_IN lang $string Language
|
|
|
|
|
_IN code $int Error code
|
|
|
|
|
_RETURN $string Error string
|
|
|
|
|
|
|
|
|
|
=end WSDL
|
|
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
2012-02-15 12:58:32 +01:00
|
|
|
|
##@method string msg(int code)
|
|
|
|
|
# calls Portal/_i18n.pm to display message in the client's language.
|
|
|
|
|
#@param $code message code
|
|
|
|
|
#@return message
|
|
|
|
|
sub msg {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my $code = shift;
|
2012-02-27 22:27:52 +01:00
|
|
|
|
return &Lemonldap::NG::Portal::_i18n::msg( $code, $self->{lang} );
|
2012-02-15 12:58:32 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
##@method string error(int code)
|
|
|
|
|
# calls Portal/_i18n.pm to display error in the client's language.
|
2010-09-16 17:10:00 +02:00
|
|
|
|
#@param $code optional error code
|
2008-12-26 18:58:48 +01:00
|
|
|
|
#@return error message
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub error {
|
|
|
|
|
my $self = shift;
|
2008-12-08 11:56:19 +01:00
|
|
|
|
my $code = shift || $self->{error};
|
2012-06-12 17:46:18 +02:00
|
|
|
|
if ( my $lang = shift ) { # only for SOAP error requests
|
2012-05-24 18:10:15 +02:00
|
|
|
|
$self->{lang} = $self->extract_lang($lang);
|
|
|
|
|
}
|
2011-07-01 10:36:12 +02:00
|
|
|
|
my $msg;
|
|
|
|
|
|
|
|
|
|
# Check for customized message
|
2012-02-27 22:27:52 +01:00
|
|
|
|
foreach ( @{ $self->{lang} } ) {
|
2012-02-15 12:58:32 +01:00
|
|
|
|
if ( $self->{ "error_" . $_ . "_" . $code } ) {
|
|
|
|
|
$msg = $self->{ "error_" . $_ . "_" . $code };
|
|
|
|
|
last;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$msg ||= $self->{ "error_" . $code };
|
2011-07-01 10:36:12 +02:00
|
|
|
|
|
|
|
|
|
# Use customized message or built-in message
|
2012-06-12 17:46:18 +02:00
|
|
|
|
if ( defined $msg ) {
|
2012-02-29 10:36:16 +01:00
|
|
|
|
|
|
|
|
|
# Manage UTF-8
|
|
|
|
|
utf8::decode($msg);
|
|
|
|
|
|
|
|
|
|
$self->lmLog( "Use customized message $msg for error $code", 'debug' );
|
2011-07-01 10:36:12 +02:00
|
|
|
|
}
|
|
|
|
|
else {
|
2012-02-27 22:27:52 +01:00
|
|
|
|
$msg = &Lemonldap::NG::Portal::_i18n::error( $code, $self->{lang} );
|
2011-07-01 10:36:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Return message
|
|
|
|
|
# Manage SOAP
|
2012-05-24 18:10:15 +02:00
|
|
|
|
return $msg;
|
2006-12-18 12:32:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-29 11:28:31 +01:00
|
|
|
|
##@method string error_type(int code)
|
2008-09-18 10:34:17 +02:00
|
|
|
|
# error_type tells if error is positive, warning or negative
|
2008-12-28 09:36:52 +01:00
|
|
|
|
# @param $code Lemonldap::NG error code
|
|
|
|
|
# @return "positive", "warning" or "negative"
|
2008-09-18 10:34:17 +02:00
|
|
|
|
sub error_type {
|
|
|
|
|
my $self = shift;
|
2008-12-07 21:07:52 +01:00
|
|
|
|
my $code = shift || $self->{error};
|
2008-09-18 10:34:17 +02:00
|
|
|
|
|
|
|
|
|
# Positive errors
|
2008-10-07 22:15:48 +02:00
|
|
|
|
return "positive"
|
|
|
|
|
if (
|
|
|
|
|
scalar(
|
2010-02-20 12:44:05 +01:00
|
|
|
|
grep { /^$code$/ } (
|
2011-11-04 16:37:42 +01:00
|
|
|
|
PE_REDIRECT, PE_DONE,
|
|
|
|
|
PE_OK, PE_PASSWORD_OK,
|
|
|
|
|
PE_MAILOK, PE_LOGOUT_OK,
|
|
|
|
|
PE_MAILFIRSTACCESS, PE_PASSWORDFIRSTACCESS,
|
2014-05-26 18:25:33 +02:00
|
|
|
|
PE_MAILCONFIRMOK, PE_REGISTERFIRSTACCESS,
|
2010-02-20 12:44:05 +01:00
|
|
|
|
)
|
2008-10-07 22:15:48 +02:00
|
|
|
|
)
|
|
|
|
|
);
|
2008-09-18 10:34:17 +02:00
|
|
|
|
|
|
|
|
|
# Warning errors
|
2008-10-07 22:15:48 +02:00
|
|
|
|
return "warning"
|
|
|
|
|
if (
|
|
|
|
|
scalar(
|
2008-12-07 21:07:52 +01:00
|
|
|
|
grep { /^$code$/ } (
|
2011-07-07 12:35:04 +02:00
|
|
|
|
PE_INFO, PE_SESSIONEXPIRED,
|
|
|
|
|
PE_FORMEMPTY, PE_FIRSTACCESS,
|
|
|
|
|
PE_PP_GRACE, PE_PP_EXP_WARNING,
|
|
|
|
|
PE_NOTIFICATION, PE_BADURL,
|
|
|
|
|
PE_CONFIRM, PE_MAILFORMEMPTY,
|
|
|
|
|
PE_MAILCONFIRMATION_ALREADY_SENT, PE_PASSWORDFORMEMPTY,
|
2014-05-26 18:25:33 +02:00
|
|
|
|
PE_CAPTCHAEMPTY, PE_REGISTERFORMEMPTY,
|
2008-10-07 22:15:48 +02:00
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
);
|
2008-09-18 10:34:17 +02:00
|
|
|
|
|
|
|
|
|
# Negative errors (default)
|
|
|
|
|
return "negative";
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-28 09:36:52 +01:00
|
|
|
|
##@method void header()
|
2008-12-26 18:58:48 +01:00
|
|
|
|
# Overload CGI::header() to add Lemonldap::NG cookie.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub header {
|
|
|
|
|
my $self = shift;
|
2010-10-11 13:45:37 +02:00
|
|
|
|
unshift @_, '-type' unless ($#_);
|
2006-12-18 12:32:33 +01:00
|
|
|
|
if ( $self->{cookie} ) {
|
|
|
|
|
$self->SUPER::header( @_, -cookie => $self->{cookie} );
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->SUPER::header(@_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-28 09:36:52 +01:00
|
|
|
|
##@method void redirect()
|
2008-12-26 18:58:48 +01:00
|
|
|
|
# Overload CGI::redirect() to add Lemonldap::NG cookie.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub redirect {
|
|
|
|
|
my $self = shift;
|
2007-07-30 21:38:19 +02:00
|
|
|
|
if ( $self->{cookie} ) {
|
|
|
|
|
$self->SUPER::redirect( @_, -cookie => $self->{cookie} );
|
2006-12-18 12:32:33 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->SUPER::redirect(@_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-25 12:01:17 +02:00
|
|
|
|
## @method protected hashref getApacheSession(string id, boolean noInfo, boolean $force)
|
2009-02-14 09:55:19 +01:00
|
|
|
|
# Try to recover the session corresponding to id and return session datas.
|
2014-06-25 12:01:17 +02:00
|
|
|
|
# If $id is set to undef or if $force is true, return a new session.
|
2010-07-05 11:36:52 +02:00
|
|
|
|
# @param id session reference
|
|
|
|
|
# @param noInfo do not set Apache REMOTE_USER
|
2014-06-25 12:01:17 +02:00
|
|
|
|
# @param force Force session creation if it does not exist
|
2014-02-26 11:57:49 +01:00
|
|
|
|
# return Lemonldap::NG::Common::Session object
|
2009-02-23 18:35:38 +01:00
|
|
|
|
sub getApacheSession {
|
2014-06-25 12:01:17 +02:00
|
|
|
|
my ( $self, $id, $noInfo, $force ) = @_;
|
2008-10-05 20:42:50 +02:00
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $apacheSession = Lemonldap::NG::Common::Session->new(
|
|
|
|
|
{
|
|
|
|
|
storageModule => $self->{globalStorage},
|
|
|
|
|
storageModuleOptions => $self->{globalStorageOptions},
|
|
|
|
|
cacheModule => $self->{localSessionStorage},
|
|
|
|
|
cacheModuleOptions => $self->{localSessionStorageOptions},
|
|
|
|
|
id => $id,
|
2014-06-25 12:01:17 +02:00
|
|
|
|
force => $force,
|
2014-02-26 11:57:49 +01:00
|
|
|
|
kind => "SSO",
|
2008-10-05 20:42:50 +02:00
|
|
|
|
}
|
2014-02-26 11:57:49 +01:00
|
|
|
|
);
|
|
|
|
|
|
2014-07-24 17:37:12 +02:00
|
|
|
|
if ( $apacheSession->error ) {
|
|
|
|
|
$self->lmLog( $apacheSession->error, 'debug' );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-02-26 11:57:49 +01:00
|
|
|
|
|
2015-06-12 12:56:38 +02:00
|
|
|
|
if ( $id and !$force and !$apacheSession->data ) {
|
|
|
|
|
$self->lmLog( "Session $id not found", 'debug' );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-30 07:27:06 +02:00
|
|
|
|
unless ($noInfo) {
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$self->setApacheUser( $apacheSession->data->{ $self->{whatToTrace} } )
|
|
|
|
|
if ($id);
|
|
|
|
|
$self->{id} = $apacheSession->id;
|
2010-04-30 07:27:06 +02:00
|
|
|
|
}
|
2014-02-26 11:57:49 +01:00
|
|
|
|
return $apacheSession;
|
2008-10-05 20:42:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
2011-06-10 14:20:49 +02:00
|
|
|
|
## @method protected hashref getPersistentSession(string id)
|
|
|
|
|
# Try to recover the persitent session corresponding to id and return session datas.
|
|
|
|
|
# If $id is set to undef, return a new session.
|
|
|
|
|
# @param id session reference
|
2014-02-26 11:57:49 +01:00
|
|
|
|
# return Lemonldap::NG::Common::Session object
|
2011-06-10 14:20:49 +02:00
|
|
|
|
sub getPersistentSession {
|
|
|
|
|
my ( $self, $id ) = splice @_;
|
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $persistentSession = Lemonldap::NG::Common::Session->new(
|
|
|
|
|
{
|
|
|
|
|
storageModule => $self->{persistentStorage},
|
|
|
|
|
storageModuleOptions => $self->{persistentStorageOptions},
|
|
|
|
|
cacheModule => $self->{localSessionStorage},
|
|
|
|
|
cacheModuleOptions => $self->{localSessionStorageOptions},
|
|
|
|
|
id => $id,
|
|
|
|
|
force => 1,
|
|
|
|
|
kind => "Persistent",
|
2011-06-10 14:20:49 +02:00
|
|
|
|
}
|
2014-02-26 11:57:49 +01:00
|
|
|
|
);
|
|
|
|
|
|
2014-07-24 17:37:12 +02:00
|
|
|
|
if ( $persistentSession->error ) {
|
|
|
|
|
$self->lmLog( $persistentSession->error, 'debug' );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
return $persistentSession;
|
2011-06-10 14:20:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-08 18:02:43 +02:00
|
|
|
|
## @method protected string _md5hash(string s)
|
|
|
|
|
# Return md5(s)
|
|
|
|
|
# @param $s String to hash
|
|
|
|
|
# @return hashed value
|
|
|
|
|
sub _md5hash {
|
|
|
|
|
my ( $self, $s ) = splice @_;
|
|
|
|
|
return substr( Digest::MD5::md5_hex($s), 0, 32 );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-12 15:32:18 +02:00
|
|
|
|
## @method void updatePersistentSession(hashRef infos, string uid, string id)
|
2010-10-08 17:35:40 +02:00
|
|
|
|
# Update persistent session.
|
|
|
|
|
# Call updateSession() and store %$infos in a persistent session.
|
|
|
|
|
# Note that if the session does not exists, it will be created.
|
|
|
|
|
# @param infos hash reference of information to update
|
2010-10-12 15:32:18 +02:00
|
|
|
|
# @param uid optional Unhashed persistent session ID
|
|
|
|
|
# @param id optional SSO session ID
|
2010-10-08 17:35:40 +02:00
|
|
|
|
# @return nothing
|
|
|
|
|
sub updatePersistentSession {
|
2010-10-12 15:32:18 +02:00
|
|
|
|
my ( $self, $infos, $uid, $id ) = splice @_;
|
2010-10-08 17:35:40 +02:00
|
|
|
|
|
|
|
|
|
# Return if no infos to update
|
2010-10-08 18:14:06 +02:00
|
|
|
|
return () unless ( ref $infos eq 'HASH' and %$infos );
|
2010-10-08 17:35:40 +02:00
|
|
|
|
|
2010-10-12 15:32:18 +02:00
|
|
|
|
# Update current session
|
2011-06-09 16:30:50 +02:00
|
|
|
|
$self->updateSession( $infos, $id );
|
2010-10-08 17:35:40 +02:00
|
|
|
|
|
2010-10-08 18:14:06 +02:00
|
|
|
|
$uid ||= $self->{sessionInfo}->{ $self->{whatToTrace} };
|
|
|
|
|
return () unless ($uid);
|
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $persistentSession =
|
|
|
|
|
$self->getPersistentSession( $self->_md5hash($uid) );
|
|
|
|
|
|
|
|
|
|
$persistentSession->update($infos);
|
2014-07-24 17:37:12 +02:00
|
|
|
|
|
|
|
|
|
if ( $persistentSession->error ) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Cannot update persistent session " . $self->_md5hash($uid),
|
|
|
|
|
'error' );
|
|
|
|
|
$self->lmLog( $persistentSession->error, 'error' );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-08 17:35:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-12 15:50:42 +02:00
|
|
|
|
## @method void updateSession(hashRef infos, string id)
|
2008-12-26 18:58:48 +01:00
|
|
|
|
# Update session stored.
|
2010-04-12 15:50:42 +02:00
|
|
|
|
# If no id is given, try to get it from cookie.
|
|
|
|
|
# If the session is available, update datas with $info.
|
2012-02-08 16:47:36 +01:00
|
|
|
|
# Note that outdated session data may remain some time on
|
|
|
|
|
# server local cache, if there are several LL::NG servers.
|
2010-06-08 12:39:34 +02:00
|
|
|
|
# @param infos hash reference of information to update
|
2010-04-12 15:50:42 +02:00
|
|
|
|
# @param id Session ID
|
|
|
|
|
# @return nothing
|
2008-10-16 09:35:42 +02:00
|
|
|
|
sub updateSession {
|
2010-04-12 15:50:42 +02:00
|
|
|
|
my ( $self, $infos, $id ) = splice @_;
|
2008-10-16 09:35:42 +02:00
|
|
|
|
|
2010-10-01 11:06:32 +02:00
|
|
|
|
# Return if no infos to update
|
2010-10-08 18:14:06 +02:00
|
|
|
|
return () unless ( ref $infos eq 'HASH' and %$infos );
|
2010-10-01 11:06:32 +02:00
|
|
|
|
|
2010-09-29 12:09:04 +02:00
|
|
|
|
# Recover session ID unless given
|
|
|
|
|
$id ||= $self->{id};
|
2010-10-08 17:35:40 +02:00
|
|
|
|
unless ($id) {
|
|
|
|
|
my %cookies = fetch CGI::Cookie;
|
2010-10-14 11:50:23 +02:00
|
|
|
|
$id ||= $cookies{ $self->{cookieName} }->value
|
|
|
|
|
if ( defined $cookies{ $self->{cookieName} } );
|
2010-10-08 17:35:40 +02:00
|
|
|
|
}
|
2010-04-12 15:50:42 +02:00
|
|
|
|
|
2011-06-09 16:30:50 +02:00
|
|
|
|
if ($id) {
|
2012-02-09 22:56:24 +01:00
|
|
|
|
|
2012-02-08 16:47:36 +01:00
|
|
|
|
# Update sessionInfo data
|
|
|
|
|
## sessionInfo updated if $id defined : quite strange !!
|
|
|
|
|
## See http://jira.ow2.org/browse/LEMONLDAP-430
|
2011-06-09 16:30:50 +02:00
|
|
|
|
foreach ( keys %$infos ) {
|
|
|
|
|
$self->lmLog( "Update sessionInfo $_ with " . $infos->{$_},
|
|
|
|
|
'debug' );
|
|
|
|
|
$self->{sessionInfo}->{$_} = $infos->{$_};
|
|
|
|
|
}
|
2011-11-07 12:42:29 +01:00
|
|
|
|
|
2012-02-08 16:47:36 +01:00
|
|
|
|
# Update session in global storage
|
2014-02-26 11:57:49 +01:00
|
|
|
|
if ( my $apacheSession = $self->getApacheSession( $id, 1 ) ) {
|
2008-10-16 09:35:42 +02:00
|
|
|
|
|
2012-02-08 16:47:36 +01:00
|
|
|
|
# Store updateTime
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$infos->{updateTime} = strftime( "%Y%m%d%H%M%S", localtime() );
|
2010-01-25 18:40:46 +01:00
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
# Store/update session values
|
|
|
|
|
$apacheSession->update($infos);
|
2014-07-24 17:37:12 +02:00
|
|
|
|
|
|
|
|
|
if ( $apacheSession->error ) {
|
|
|
|
|
$self->lmLog( "Cannot update session $id", 'error' );
|
|
|
|
|
$self->lmLog( $apacheSession->error, 'error' );
|
|
|
|
|
}
|
2012-02-08 16:47:36 +01:00
|
|
|
|
}
|
2008-10-16 09:35:42 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
## @method void addSessionValue(string key, string value, string id)
|
|
|
|
|
# Add a value into session key if not already present
|
|
|
|
|
# @param key Session key
|
|
|
|
|
# @param value Value to add
|
|
|
|
|
# @param id optional Session identifier
|
|
|
|
|
sub addSessionValue {
|
|
|
|
|
my ( $self, $key, $value, $id ) = splice @_;
|
|
|
|
|
|
|
|
|
|
# Mandatory parameters
|
2010-10-08 18:14:06 +02:00
|
|
|
|
return () unless defined $key;
|
|
|
|
|
return () unless defined $value;
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
|
|
|
|
# Get current key value
|
|
|
|
|
my $old_value = $self->{sessionInfo}->{$key};
|
|
|
|
|
|
|
|
|
|
# Split old values
|
|
|
|
|
if ( defined $old_value ) {
|
|
|
|
|
my @old_values = split /\Q$self->{multiValuesSeparator}\E/, $old_value;
|
|
|
|
|
|
|
|
|
|
# Do nothing if value already exists
|
|
|
|
|
foreach (@old_values) {
|
2010-10-08 18:14:06 +02:00
|
|
|
|
return () if ( $_ eq $value );
|
2010-08-23 15:27:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Add separator
|
|
|
|
|
$old_value .= $self->{multiValuesSeparator};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$old_value = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Store new value
|
|
|
|
|
my $new_value = $old_value . $value;
|
|
|
|
|
$self->updateSession( { $key => $new_value }, $id );
|
|
|
|
|
|
|
|
|
|
# Return
|
2010-10-08 18:14:06 +02:00
|
|
|
|
return ();
|
2010-08-23 15:27:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-05-21 11:03:29 +02:00
|
|
|
|
## @method string getFirstValue(string value)
|
|
|
|
|
# Get the first value of a multivaluated session value
|
|
|
|
|
# @param value the complete value
|
|
|
|
|
# @return first value
|
|
|
|
|
sub getFirstValue {
|
|
|
|
|
my ( $self, $value ) = splice @_;
|
|
|
|
|
|
|
|
|
|
my @values = split /\Q$self->{multiValuesSeparator}\E/, $value;
|
|
|
|
|
|
|
|
|
|
return $values[0];
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-28 09:36:52 +01:00
|
|
|
|
##@method protected int _subProcess(array @subs)
|
2008-12-26 18:58:48 +01:00
|
|
|
|
# Execute methods until an error is returned.
|
|
|
|
|
# If $self->{$sub} exists, launch it, else launch $self->$sub
|
|
|
|
|
#@param @subs array list of subroutines
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal error
|
2007-10-22 21:42:19 +02:00
|
|
|
|
sub _subProcess {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my @subs = @_;
|
|
|
|
|
my $err = undef;
|
|
|
|
|
|
|
|
|
|
foreach my $sub (@subs) {
|
2009-02-17 16:39:14 +01:00
|
|
|
|
last if ( $err = $self->_sub($sub) );
|
|
|
|
|
}
|
2007-10-22 21:42:19 +02:00
|
|
|
|
return $err;
|
|
|
|
|
}
|
2010-01-28 15:47:51 +01:00
|
|
|
|
|
2008-12-28 09:36:52 +01:00
|
|
|
|
##@method protected void updateStatus()
|
2008-12-26 18:58:48 +01:00
|
|
|
|
# Inform status mechanism module.
|
|
|
|
|
# If an handler is launched on the same server with "status=>1", inform the
|
|
|
|
|
# status module with the result (portal error).
|
2008-05-11 21:21:39 +02:00
|
|
|
|
sub updateStatus {
|
2009-04-07 22:38:24 +02:00
|
|
|
|
my $self = shift;
|
2008-05-11 21:21:39 +02:00
|
|
|
|
print $Lemonldap::NG::Handler::Simple::statusPipe (
|
2013-01-03 19:28:55 +01:00
|
|
|
|
$self->{user} ? $self->{user} : $self->ipAddr )
|
2008-05-11 21:21:39 +02:00
|
|
|
|
. " => $ENV{SERVER_NAME}$ENV{SCRIPT_NAME} "
|
|
|
|
|
. $self->{error} . "\n"
|
|
|
|
|
if ($Lemonldap::NG::Handler::Simple::statusPipe);
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@method protected string notification()
|
|
|
|
|
#@return Notification stored by checkNotification()
|
2008-11-24 07:57:18 +01:00
|
|
|
|
sub notification {
|
2009-04-07 22:38:24 +02:00
|
|
|
|
my $self = shift;
|
2008-11-24 07:57:18 +01:00
|
|
|
|
return $self->{_notification};
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@method protected string get_url()
|
2009-04-08 18:31:13 +02:00
|
|
|
|
# Return url parameter
|
2008-12-28 09:36:52 +01:00
|
|
|
|
# @return url parameter if good, nothing else.
|
2008-12-03 17:41:30 +01:00
|
|
|
|
sub get_url {
|
2009-04-07 22:38:24 +02:00
|
|
|
|
my $self = shift;
|
2009-04-11 13:16:44 +02:00
|
|
|
|
return $self->{_url};
|
2008-12-03 17:41:30 +01:00
|
|
|
|
}
|
2008-06-06 05:51:39 +02:00
|
|
|
|
|
2009-05-19 10:52:27 +02:00
|
|
|
|
##@method protected string get_user()
|
|
|
|
|
# Return user parameter
|
|
|
|
|
# @return user parameter if good, nothing else.
|
|
|
|
|
sub get_user {
|
|
|
|
|
my $self = shift;
|
2014-01-17 23:32:18 +01:00
|
|
|
|
|
|
|
|
|
return undef unless $self->{user};
|
|
|
|
|
unless ( $self->{user} =~ /$self->{userControl}/o ) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Value "
|
|
|
|
|
. $self->{user}
|
|
|
|
|
. " does not match userControl regexp: "
|
|
|
|
|
. $self->{userControl},
|
|
|
|
|
'warn'
|
|
|
|
|
);
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $self->{user};
|
2009-05-19 10:52:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-15 10:53:56 +01:00
|
|
|
|
## @method string get_module(string type)
|
|
|
|
|
# Return current used module
|
|
|
|
|
# @param type auth/user/password/issuer
|
|
|
|
|
# @return module name
|
|
|
|
|
sub get_module {
|
|
|
|
|
my ( $self, $type ) = splice @_;
|
|
|
|
|
|
|
|
|
|
if ( $type =~ /auth/i ) {
|
|
|
|
|
if ( defined $self->{_multi}->{stack}->[0] ) {
|
2015-09-24 08:58:21 +02:00
|
|
|
|
return $self->{_multi}->{stack}->[0]->[0]->{s};
|
2010-03-15 10:53:56 +01:00
|
|
|
|
}
|
2010-09-10 21:52:44 +02:00
|
|
|
|
if ( defined $self->{_choice}->{modules} ) {
|
|
|
|
|
return $self->{_choice}->{modules}->[0]->{n};
|
|
|
|
|
}
|
2010-03-15 10:53:56 +01:00
|
|
|
|
else {
|
|
|
|
|
return $self->{authentication};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $type =~ /user/i ) {
|
|
|
|
|
if ( defined $self->{_multi}->{stack}->[1] ) {
|
2015-09-24 08:58:21 +02:00
|
|
|
|
return $self->{_multi}->{stack}->[1]->[0]->{s};
|
2010-03-15 10:53:56 +01:00
|
|
|
|
}
|
2010-09-10 21:52:44 +02:00
|
|
|
|
if ( defined $self->{_choice}->{modules} ) {
|
|
|
|
|
return $self->{_choice}->{modules}->[1]->{n};
|
|
|
|
|
}
|
2010-03-15 10:53:56 +01:00
|
|
|
|
else {
|
|
|
|
|
return $self->{userDB};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $type =~ /password/i ) {
|
2010-09-10 21:52:44 +02:00
|
|
|
|
if ( defined $self->{_choice}->{modules} ) {
|
|
|
|
|
return $self->{_choice}->{modules}->[2]->{n};
|
|
|
|
|
}
|
|
|
|
|
else {
|
2010-09-23 18:41:39 +02:00
|
|
|
|
return $self->{passwordDB};
|
|
|
|
|
}
|
2010-09-10 21:52:44 +02:00
|
|
|
|
}
|
2010-03-15 10:53:56 +01:00
|
|
|
|
|
|
|
|
|
if ( $type =~ /issuer/i ) {
|
2010-08-23 15:27:16 +02:00
|
|
|
|
return $self->{_activeIssuerDB};
|
2010-03-15 10:53:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-28 09:36:52 +01:00
|
|
|
|
##@method private Safe safe()
|
2008-12-11 18:02:02 +01:00
|
|
|
|
# Provide the security jail.
|
|
|
|
|
#@return Safe object
|
|
|
|
|
sub safe {
|
|
|
|
|
my $self = shift;
|
2011-02-07 11:27:36 +01:00
|
|
|
|
|
2011-03-16 14:58:17 +01:00
|
|
|
|
# Test if safe already exists
|
|
|
|
|
if ($safe) {
|
|
|
|
|
|
|
|
|
|
# Refresh the portal object inside it
|
|
|
|
|
$safe->{p} = $self;
|
|
|
|
|
|
2013-07-25 15:13:48 +02:00
|
|
|
|
# Refresh environment variables
|
|
|
|
|
$safe->share_from( 'main', ['%ENV'] );
|
|
|
|
|
|
2011-03-16 14:58:17 +01:00
|
|
|
|
return $safe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Else create it
|
2011-02-07 11:27:36 +01:00
|
|
|
|
$safe = Lemonldap::NG::Common::Safe->new($self);
|
|
|
|
|
|
|
|
|
|
# Get custom functions
|
2008-12-11 18:02:02 +01:00
|
|
|
|
my @t =
|
2010-09-03 15:21:03 +02:00
|
|
|
|
$self->{customFunctions}
|
|
|
|
|
? split( /\s+/, $self->{customFunctions} )
|
|
|
|
|
: ();
|
2008-12-11 18:02:02 +01:00
|
|
|
|
foreach (@t) {
|
|
|
|
|
my $sub = $_;
|
|
|
|
|
unless (/::/) {
|
|
|
|
|
$sub = ref($self) . "::$_";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
s/^.*:://;
|
|
|
|
|
}
|
|
|
|
|
next if ( $self->can($_) );
|
|
|
|
|
eval "sub $_ {
|
|
|
|
|
return $sub( '$self->{portal}', \@_ );
|
|
|
|
|
}";
|
2009-02-12 20:48:53 +01:00
|
|
|
|
$self->lmLog( $@, 'error' ) if ($@);
|
2008-12-11 18:02:02 +01:00
|
|
|
|
}
|
2011-02-07 11:27:36 +01:00
|
|
|
|
|
|
|
|
|
# Share %ENV
|
2009-03-08 18:37:31 +01:00
|
|
|
|
$safe->share_from( 'main', ['%ENV'] );
|
2011-02-07 11:27:36 +01:00
|
|
|
|
|
|
|
|
|
# Share Safelib
|
2009-04-05 10:12:16 +02:00
|
|
|
|
$safe->share_from( 'Lemonldap::NG::Common::Safelib',
|
|
|
|
|
$Lemonldap::NG::Common::Safelib::functions );
|
2011-02-07 11:27:36 +01:00
|
|
|
|
|
|
|
|
|
# Share custom functions and &encode_base64
|
2009-03-08 18:37:31 +01:00
|
|
|
|
$safe->share( '&encode_base64', @t );
|
2011-02-07 11:27:36 +01:00
|
|
|
|
|
2008-12-11 18:02:02 +01:00
|
|
|
|
return $safe;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
##@method private boolean _deleteSession(Lemonldap::NG::Common::Session session, boolean preserveCookie)
|
2010-01-12 10:53:49 +01:00
|
|
|
|
# Delete an existing session. If "securedCookie" is set to 2, the http session
|
|
|
|
|
# will also be removed.
|
2010-02-18 18:22:04 +01:00
|
|
|
|
# @param h tied Apache::Session object
|
|
|
|
|
# @param preserveCookie do not delete cookie
|
2010-01-12 10:53:49 +01:00
|
|
|
|
# @return True if session has been deleted
|
2009-04-03 18:17:57 +02:00
|
|
|
|
sub _deleteSession {
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my ( $self, $session, $preserveCookie ) = @_;
|
2010-05-17 18:02:21 +02:00
|
|
|
|
|
2012-02-07 17:18:46 +01:00
|
|
|
|
# Invalidate http cookie and session, if set
|
|
|
|
|
if ( $self->{securedCookie} >= 2 ) {
|
|
|
|
|
|
|
|
|
|
# Try to find a linked http session (securedCookie == 2)
|
2014-02-26 11:57:49 +01:00
|
|
|
|
if ( my $id2 = $session->data->{_httpSession} ) {
|
|
|
|
|
if ( my $session2 = $self->getApacheSession( $id2, 1 ) ) {
|
|
|
|
|
$session2->remove;
|
2014-07-24 17:37:12 +02:00
|
|
|
|
if ( $session2->error ) {
|
|
|
|
|
$self->lmLog( "Unable to remove linked session $id2",
|
|
|
|
|
'debug' );
|
|
|
|
|
$self->lmLog( $session2->error, 'debug' );
|
|
|
|
|
}
|
2012-02-07 17:18:46 +01:00
|
|
|
|
}
|
2010-01-15 23:01:04 +01:00
|
|
|
|
}
|
2012-02-07 17:18:46 +01:00
|
|
|
|
|
|
|
|
|
# Create an obsolete cookie to remove it
|
|
|
|
|
push @{ $self->{cookie} },
|
|
|
|
|
$self->cookie(
|
|
|
|
|
-name => $self->{cookieName} . 'http',
|
|
|
|
|
-value => 0,
|
|
|
|
|
-domain => $self->{domain},
|
|
|
|
|
-path => "/",
|
|
|
|
|
-secure => 0,
|
|
|
|
|
-expires => '-1d',
|
|
|
|
|
@_,
|
2014-02-26 11:57:49 +01:00
|
|
|
|
) unless ($preserveCookie);
|
2010-01-12 10:53:49 +01:00
|
|
|
|
}
|
2010-02-18 18:22:04 +01:00
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$session->remove;
|
2009-04-03 18:17:57 +02:00
|
|
|
|
|
2010-01-12 10:53:49 +01:00
|
|
|
|
# Create an obsolete cookie to remove it
|
2009-04-03 18:17:57 +02:00
|
|
|
|
push @{ $self->{cookie} },
|
|
|
|
|
$self->cookie(
|
|
|
|
|
-name => $self->{cookieName},
|
|
|
|
|
-value => 0,
|
|
|
|
|
-domain => $self->{domain},
|
|
|
|
|
-path => "/",
|
|
|
|
|
-secure => 0,
|
|
|
|
|
-expires => '-1d',
|
|
|
|
|
@_,
|
2010-01-12 11:36:04 +01:00
|
|
|
|
) unless ($preserveCookie);
|
2010-01-12 10:53:49 +01:00
|
|
|
|
|
|
|
|
|
# Log
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $user = $self->{sessionInfo}->{ $self->{whatToTrace} };
|
2012-02-29 17:01:13 +01:00
|
|
|
|
$self->_sub( 'userNotice', "User $user has been disconnected" )
|
|
|
|
|
if $user;
|
2010-01-12 10:53:49 +01:00
|
|
|
|
|
2014-07-24 17:37:12 +02:00
|
|
|
|
return $session->error ? 0 : 1;
|
2009-04-03 18:17:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-03 12:26:50 +02:00
|
|
|
|
##@method private void _dump(void* variable)
|
2010-02-04 13:30:18 +01:00
|
|
|
|
# Dump variable in debug mode
|
|
|
|
|
# @param $variable
|
|
|
|
|
# @return void
|
|
|
|
|
sub _dump {
|
2010-03-01 21:32:28 +01:00
|
|
|
|
my $self = shift;
|
|
|
|
|
my $variable = shift;
|
2010-02-04 13:30:18 +01:00
|
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
|
require Data::Dumper;
|
2015-09-25 17:29:57 +02:00
|
|
|
|
$Data::Dumper::Indent = 0;
|
2010-04-28 21:57:16 +02:00
|
|
|
|
$self->lmLog( "Dump: " . Data::Dumper::Dumper($variable), 'debug' );
|
2010-02-04 13:30:18 +01:00
|
|
|
|
|
2010-03-01 21:32:28 +01:00
|
|
|
|
return;
|
2010-02-04 13:30:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
2010-01-11 17:04:36 +01:00
|
|
|
|
##@method protected string info(string t)
|
|
|
|
|
# Get or set info to display to the user.
|
|
|
|
|
# @param $t optional text to store
|
|
|
|
|
# @return HTML text to display
|
|
|
|
|
sub info {
|
|
|
|
|
my ( $self, $t ) = @_;
|
2010-01-12 10:53:49 +01:00
|
|
|
|
$self->{_info} .= $t if ( defined $t );
|
2010-01-11 17:04:36 +01:00
|
|
|
|
return $self->{_info};
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-18 15:39:15 +02:00
|
|
|
|
##@method protected string loginInfo(string t)
|
|
|
|
|
# Get or set info to display to the user on login screen
|
|
|
|
|
# @param $t optional text to store
|
|
|
|
|
# @return HTML text to display
|
|
|
|
|
sub loginInfo {
|
|
|
|
|
my ( $self, $t ) = @_;
|
|
|
|
|
$self->{_loginInfo} .= $t if ( defined $t );
|
|
|
|
|
return $self->{_loginInfo};
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-29 15:39:26 +02:00
|
|
|
|
##@method public void printImage(string file, string type)
|
|
|
|
|
# Print image to STDOUT
|
|
|
|
|
# @param $file The path to the file to print
|
|
|
|
|
# @param $type The content-type to use (ie: image/png)
|
|
|
|
|
# @return void
|
|
|
|
|
sub printImage {
|
|
|
|
|
my ( $self, $file, $type ) = @_;
|
|
|
|
|
binmode STDOUT;
|
2010-05-01 15:12:28 +02:00
|
|
|
|
unless ( open( IMAGE, '<', $file ) ) {
|
2010-04-29 15:39:26 +02:00
|
|
|
|
$self->lmLog( "Could not display image '$file'", 'error' );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
print $self->header(
|
2010-05-01 15:12:28 +02:00
|
|
|
|
$type . '; charset=utf-8; content-length=' . ( stat($file) )[10] );
|
2010-04-29 15:39:26 +02:00
|
|
|
|
my $buffer = "";
|
2010-05-01 15:12:28 +02:00
|
|
|
|
while ( read( IMAGE, $buffer, 4096 ) ) {
|
2010-04-29 15:39:26 +02:00
|
|
|
|
print $buffer;
|
|
|
|
|
}
|
|
|
|
|
close(IMAGE);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-24 14:02:57 +02:00
|
|
|
|
sub stamp {
|
|
|
|
|
my $self = shift;
|
2010-09-24 16:21:19 +02:00
|
|
|
|
return $self->{cipher} ? $self->{cipher}->encrypt( time() ) : 1;
|
2010-09-24 14:02:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-16 11:58:27 +02:00
|
|
|
|
## @method string convertSec(int sec)
|
|
|
|
|
# Convert seconds to hours, minutes, seconds
|
2013-10-19 18:34:20 +02:00
|
|
|
|
# @param $sec number of seconds
|
2012-07-16 11:58:27 +02:00
|
|
|
|
# @return a formated time
|
|
|
|
|
sub convertSec {
|
|
|
|
|
my ( $self, $sec ) = splice @_;
|
2012-07-26 04:47:27 +02:00
|
|
|
|
my ( $day, $hrs, $min ) = ( 0, 0, 0 );
|
2012-07-16 11:58:27 +02:00
|
|
|
|
|
2012-07-26 04:47:27 +02:00
|
|
|
|
# Calculate the minutes
|
2012-07-16 15:06:16 +02:00
|
|
|
|
if ( $sec > 60 ) {
|
|
|
|
|
$min = $sec / 60, $sec %= 60;
|
|
|
|
|
$min = int($min);
|
|
|
|
|
}
|
2012-07-16 11:58:27 +02:00
|
|
|
|
|
|
|
|
|
# Calculate the hours
|
2012-07-26 04:47:27 +02:00
|
|
|
|
if ( $min > 60 ) {
|
2012-07-16 15:06:16 +02:00
|
|
|
|
$hrs = $min / 60, $min %= 60;
|
2012-07-26 04:47:27 +02:00
|
|
|
|
$hrs = int($hrs);
|
2012-07-16 15:06:16 +02:00
|
|
|
|
}
|
2012-07-16 11:58:27 +02:00
|
|
|
|
|
|
|
|
|
# Calculate the days
|
2012-07-16 15:06:16 +02:00
|
|
|
|
if ( $hrs > 24 ) {
|
|
|
|
|
$day = $hrs / 24, $hrs %= 24;
|
2012-07-26 04:47:27 +02:00
|
|
|
|
$day = int($day);
|
2012-07-16 15:06:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-25 10:57:53 +02:00
|
|
|
|
# Return the date
|
2012-07-16 15:06:16 +02:00
|
|
|
|
return ( $day, $hrs, $min, $sec );
|
2012-07-16 11:58:27 +02:00
|
|
|
|
}
|
2012-07-26 04:47:27 +02:00
|
|
|
|
|
2013-08-20 15:36:06 +02:00
|
|
|
|
## @method string getSkin()
|
|
|
|
|
# Return skin name
|
|
|
|
|
# @return skin name
|
|
|
|
|
sub getSkin {
|
|
|
|
|
my ($self) = splice @_;
|
|
|
|
|
|
|
|
|
|
my $skin = $self->{portalSkin};
|
|
|
|
|
|
|
|
|
|
# Fill sessionInfo to eval rule if empty (unauthenticated user)
|
|
|
|
|
$self->{sessionInfo}->{_url} ||= $self->{urldc};
|
|
|
|
|
$self->{sessionInfo}->{ipAddr} ||= $self->ipAddr;
|
|
|
|
|
|
|
|
|
|
# Load specific skin from skinRules
|
|
|
|
|
if ( $self->{portalSkinRules} ) {
|
|
|
|
|
foreach my $skinRule ( sort keys %{ $self->{portalSkinRules} } ) {
|
|
|
|
|
if ( $self->safe->reval($skinRule) ) {
|
|
|
|
|
$skin = $self->{portalSkinRules}->{$skinRule};
|
|
|
|
|
$self->lmLog( "Skin $skin selected from skin rule", 'debug' );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-11 15:50:55 +02:00
|
|
|
|
# Check skin GET/POST parameter
|
|
|
|
|
my $skinParam = $self->param('skin');
|
|
|
|
|
if ( defined $skinParam && !$self->checkXSSAttack( 'skin', $skinParam ) ) {
|
|
|
|
|
$skin = $skinParam;
|
|
|
|
|
$self->lmLog( "Skin $skin selected from GET/POST parameter", 'debug' );
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-20 15:36:06 +02:00
|
|
|
|
return $skin;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-07 21:07:52 +01:00
|
|
|
|
###############################################################
|
|
|
|
|
# MAIN subroutine: call all steps until one returns something #
|
|
|
|
|
# different than PE_OK #
|
|
|
|
|
###############################################################
|
|
|
|
|
|
2008-12-28 09:36:52 +01:00
|
|
|
|
##@method boolean process()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Main method calling functions issued from:
|
|
|
|
|
# - itself:
|
|
|
|
|
# - controlUrlOrigin
|
|
|
|
|
# - checkNotifBack
|
|
|
|
|
# - controlExistingSession
|
|
|
|
|
# - setMacros
|
|
|
|
|
# - setLocalGroups
|
2010-10-21 12:28:47 +02:00
|
|
|
|
# - setPersistentSessionInfo
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# - removeOther
|
2010-01-11 15:02:43 +01:00
|
|
|
|
# - grantSession
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# - store
|
|
|
|
|
# - buildCookie
|
|
|
|
|
# - checkNotification
|
|
|
|
|
# - autoRedirect
|
|
|
|
|
# - updateStatus
|
|
|
|
|
# - authentication module:
|
|
|
|
|
# - authInit
|
|
|
|
|
# - extractFormInfo
|
|
|
|
|
# - setAuthSessionInfo
|
|
|
|
|
# - authenticate
|
2010-05-17 18:02:21 +02:00
|
|
|
|
# - authFinish
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# - userDB module:
|
|
|
|
|
# - userDBInit
|
|
|
|
|
# - getUser
|
|
|
|
|
# - setSessionInfo
|
|
|
|
|
# - setGroups
|
|
|
|
|
# - passwordDB module:
|
|
|
|
|
# - passwordDBInit
|
|
|
|
|
# - modifyPassword
|
|
|
|
|
# - issuerDB module:
|
|
|
|
|
# - issuerDBInit
|
|
|
|
|
# - issuerForUnAuthUser
|
|
|
|
|
# - issuerForAuthUser
|
2011-11-07 17:59:54 +01:00
|
|
|
|
# - MailReset:
|
|
|
|
|
# - sendPasswordMail
|
2009-12-10 18:03:57 +01:00
|
|
|
|
#
|
|
|
|
|
#@return 1 if all is OK, 0 if session isn't created or a notification has to be done
|
2008-12-07 21:07:52 +01:00
|
|
|
|
sub process {
|
|
|
|
|
my ($self) = @_;
|
|
|
|
|
$self->{error} = PE_OK;
|
|
|
|
|
$self->{error} = $self->_subProcess(
|
2012-02-09 10:01:04 +01:00
|
|
|
|
qw(controlUrlOrigin checkNotifBack controlExistingSession
|
|
|
|
|
issuerDBInit authInit issuerForUnAuthUser extractFormInfo
|
|
|
|
|
userDBInit getUser setAuthSessionInfo passwordDBInit
|
|
|
|
|
modifyPassword setSessionInfo setMacros setGroups
|
|
|
|
|
setPersistentSessionInfo setLocalGroups sendPasswordMail
|
2014-06-25 13:53:09 +02:00
|
|
|
|
authenticate authFinish userDBFinish passwordDBFinish
|
|
|
|
|
grantSession removeOther store buildCookie checkNotification
|
|
|
|
|
issuerForAuthUser autoRedirect)
|
2008-12-07 21:07:52 +01:00
|
|
|
|
);
|
|
|
|
|
$self->updateStatus;
|
|
|
|
|
return ( ( $self->{error} > 0 ) ? 0 : 1 );
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int controlUrlOrigin()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# If the user was redirected here, loads 'url' parameter.
|
2010-09-24 14:02:57 +02:00
|
|
|
|
# Check also confirm parameter.
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub controlUrlOrigin {
|
|
|
|
|
my $self = shift;
|
2010-09-24 14:02:57 +02:00
|
|
|
|
if ( my $c = $self->param('confirm') ) {
|
2010-10-21 15:41:26 +02:00
|
|
|
|
|
|
|
|
|
# Replace confirm stamp by 1 or -1
|
2010-09-24 14:02:57 +02:00
|
|
|
|
$c =~ s/^(-?)(.*)$/${1}1/;
|
2010-10-21 15:41:26 +02:00
|
|
|
|
|
|
|
|
|
# Decrypt confirm stamp if cipher available
|
|
|
|
|
# and confirm not already decrypted
|
|
|
|
|
if ( $self->{cipher} and $2 ne "1" ) {
|
2010-09-24 16:21:19 +02:00
|
|
|
|
my $time = time() - $self->{cipher}->decrypt($2);
|
|
|
|
|
if ( $time < 600 ) {
|
|
|
|
|
$self->lmLog( "Confirm parameter accepted $c", 'debug' );
|
|
|
|
|
$self->param( 'confirm', $c );
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->lmLog( 'Confirmation to old, refused', 'notice' );
|
|
|
|
|
$self->param( 'confirm', 0 );
|
|
|
|
|
}
|
2010-09-24 14:02:57 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-04-11 13:16:44 +02:00
|
|
|
|
$self->{_url} ||= '';
|
2009-04-08 18:31:13 +02:00
|
|
|
|
if ( my $url = $self->param('url') ) {
|
2008-12-07 10:02:44 +01:00
|
|
|
|
|
2010-08-27 18:07:19 +02:00
|
|
|
|
# REJECT NON BASE64 URL except for CAS IssuerDB
|
|
|
|
|
if ( $self->get_module('issuer') ne "CAS" ) {
|
2010-08-30 15:41:45 +02:00
|
|
|
|
if ( $url =~ m#[^A-Za-z0-9\+/=]# ) {
|
2010-09-03 16:15:44 +02:00
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Value must be in BASE64 (param: url | value: $url)",
|
2010-08-30 15:41:45 +02:00
|
|
|
|
"warn" );
|
|
|
|
|
return PE_BADURL;
|
|
|
|
|
}
|
2008-12-07 10:02:44 +01:00
|
|
|
|
|
2010-08-30 15:41:45 +02:00
|
|
|
|
$self->{urldc} = decode_base64($url);
|
|
|
|
|
$self->{urldc} =~ s/[\r\n]//sg;
|
2010-08-27 18:07:19 +02:00
|
|
|
|
}
|
|
|
|
|
else { $self->{urldc} = $url; }
|
2008-12-03 17:05:27 +01:00
|
|
|
|
|
2010-05-01 15:12:28 +02:00
|
|
|
|
# For logout request, test if Referer comes from an authorizated site
|
|
|
|
|
my $tmp =
|
|
|
|
|
( $self->param('logout') ? $ENV{HTTP_REFERER} : $self->{urldc} );
|
|
|
|
|
|
2010-09-03 16:15:44 +02:00
|
|
|
|
# XSS attack
|
2008-12-24 15:55:44 +01:00
|
|
|
|
if (
|
2010-09-03 16:15:44 +02:00
|
|
|
|
$self->checkXSSAttack(
|
|
|
|
|
$self->param('logout') ? 'HTTP Referer' : 'urldc',
|
|
|
|
|
$self->{urldc}
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
delete $self->{urldc};
|
|
|
|
|
return PE_BADURL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Non protected hosts
|
2012-05-23 20:46:38 +02:00
|
|
|
|
if ( $tmp and !$self->isTrustedUrl($tmp) ) {
|
2009-06-14 18:43:02 +02:00
|
|
|
|
$self->lmLog(
|
2010-09-03 16:15:44 +02:00
|
|
|
|
"URL contains a non protected host (param: "
|
2010-05-01 15:12:28 +02:00
|
|
|
|
. ( $self->param('logout') ? 'HTTP Referer' : 'urldc' )
|
|
|
|
|
. " | value: $tmp)",
|
2009-06-14 18:43:02 +02:00
|
|
|
|
"warn"
|
|
|
|
|
);
|
2008-12-03 17:41:30 +01:00
|
|
|
|
delete $self->{urldc};
|
2008-12-06 08:27:35 +01:00
|
|
|
|
return PE_BADURL;
|
|
|
|
|
}
|
2010-09-03 16:15:44 +02:00
|
|
|
|
|
2009-04-11 13:16:44 +02:00
|
|
|
|
$self->{_url} = $url;
|
2006-12-18 12:32:33 +01:00
|
|
|
|
}
|
2010-09-03 16:15:44 +02:00
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int checkNotifBack()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Checks if a message has been notified to the connected user.
|
2012-07-12 23:04:06 +02:00
|
|
|
|
# Call Lemonldap::NG::Common::Notification::checkNotification()
|
2009-01-30 16:26:34 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal error code
|
|
|
|
|
sub checkNotifBack {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
if ( $self->{notification} and grep( /^reference/, $self->param() ) ) {
|
2011-07-21 11:39:53 +02:00
|
|
|
|
$self->lmLog( "User was on a notification step", 'debug' );
|
2009-01-30 16:26:34 +01:00
|
|
|
|
unless ( $self->{notifObject}->checkNotification($self) ) {
|
2011-07-21 11:39:53 +02:00
|
|
|
|
$self->lmLog(
|
|
|
|
|
"All notifications have not been accepted, display them again",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
2009-01-30 16:26:34 +01:00
|
|
|
|
$self->{_notification} =
|
|
|
|
|
$self->{notifObject}->getNotification($self);
|
|
|
|
|
return PE_NOTIFICATION;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2011-07-21 11:39:53 +02:00
|
|
|
|
$self->lmLog(
|
|
|
|
|
"All notifications have been accepted, follow the authentication process",
|
|
|
|
|
'debug'
|
2009-12-11 22:17:06 +01:00
|
|
|
|
);
|
2011-07-21 11:39:53 +02:00
|
|
|
|
$self->{error} = $self->_subProcess(
|
2014-06-25 13:53:09 +02:00
|
|
|
|
qw(issuerDBInit authInit issuerForAuthUser authFinish autoRedirect)
|
|
|
|
|
);
|
2009-01-30 16:26:34 +01:00
|
|
|
|
return $self->{error} || PE_DONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int controlExistingSession(string id)
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Control existing sessions.
|
2008-12-03 14:27:30 +01:00
|
|
|
|
# To overload to control what to do with existing sessions.
|
2007-02-23 06:31:32 +01:00
|
|
|
|
# what to do with existing sessions ?
|
2008-12-03 14:27:30 +01:00
|
|
|
|
# - nothing: user is authenticated and process returns true (default)
|
|
|
|
|
# - delete and create a new session (not implemented)
|
2010-01-25 18:40:46 +01:00
|
|
|
|
# - re-authentication (set portalForceAuthn to 1)
|
2009-01-30 16:26:34 +01:00
|
|
|
|
#@param $id optional value of the session-id else cookies are examinated.
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub controlExistingSession {
|
2009-01-30 16:26:34 +01:00
|
|
|
|
my ( $self, $id ) = @_;
|
|
|
|
|
my %cookies;
|
|
|
|
|
%cookies = fetch CGI::Cookie unless ($id);
|
2008-05-11 21:21:39 +02:00
|
|
|
|
|
2014-06-10 18:21:33 +02:00
|
|
|
|
# Special request "display captcha"
|
|
|
|
|
if ( $self->param("displayCaptcha") ) {
|
|
|
|
|
|
|
|
|
|
my $captcha = Lemonldap::NG::Common::Captcha->new(
|
|
|
|
|
{
|
|
|
|
|
storageModule => $self->{captchaStorage},
|
|
|
|
|
storageModuleOptions => $self->{captchaStorageOptions},
|
|
|
|
|
md5 => $self->param("displayCaptcha"),
|
|
|
|
|
size => $self->{captcha_size},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( $captcha && $captcha->image ) {
|
|
|
|
|
binmode STDOUT;
|
|
|
|
|
print $self->header( 'image/png'
|
|
|
|
|
. '; charset=utf-8; content-length='
|
|
|
|
|
. length( $captcha->image ) );
|
|
|
|
|
print $captcha->image;
|
|
|
|
|
}
|
|
|
|
|
$self->quit();
|
|
|
|
|
}
|
|
|
|
|
|
2007-02-11 09:31:56 +01:00
|
|
|
|
# Test if Lemonldap::NG cookie is available
|
2009-01-30 16:26:34 +01:00
|
|
|
|
if (
|
|
|
|
|
$id
|
|
|
|
|
or ( $cookies{ $self->{cookieName} }
|
|
|
|
|
and $id = $cookies{ $self->{cookieName} }->value )
|
|
|
|
|
)
|
2008-05-11 21:21:39 +02:00
|
|
|
|
{
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $apacheSession = $self->getApacheSession($id);
|
2010-08-30 17:46:26 +02:00
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
if ($apacheSession) {
|
|
|
|
|
%{ $self->{sessionInfo} } = %{ $apacheSession->data };
|
2007-03-14 08:28:53 +01:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
# Logout if required
|
|
|
|
|
if ( $self->param('logout') ) {
|
2008-05-11 21:21:39 +02:00
|
|
|
|
|
2012-02-08 16:47:36 +01:00
|
|
|
|
# Delete session
|
2014-02-26 11:57:49 +01:00
|
|
|
|
unless ( $self->_deleteSession($apacheSession) ) {
|
2010-09-01 14:56:15 +02:00
|
|
|
|
$self->lmLog( "Unable to delete session $id", 'error' );
|
2014-07-24 17:37:12 +02:00
|
|
|
|
$self->lmLog( $apacheSession->error, 'error' );
|
2010-09-01 14:56:15 +02:00
|
|
|
|
return PE_ERROR;
|
|
|
|
|
}
|
2011-06-30 16:10:56 +02:00
|
|
|
|
else {
|
|
|
|
|
$self->lmLog( "Session $id deleted from global storage",
|
|
|
|
|
'debug' );
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
# Call issuerDB logout on each used issuerDBmodule
|
|
|
|
|
my $issuerDBList = $self->{sessionInfo}->{_issuerDB};
|
|
|
|
|
if ( defined $issuerDBList ) {
|
|
|
|
|
foreach my $issuerDBtype (
|
2010-08-30 17:46:26 +02:00
|
|
|
|
split(
|
|
|
|
|
/\Q$self->{multiValuesSeparator}\E/,
|
|
|
|
|
$issuerDBList
|
|
|
|
|
)
|
2010-09-01 14:56:15 +02:00
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
my $module_name =
|
|
|
|
|
'Lemonldap::NG::Portal::IssuerDB' . $issuerDBtype;
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Process logout for issuerDB module $issuerDBtype",
|
2010-08-30 17:46:26 +02:00
|
|
|
|
'debug'
|
|
|
|
|
);
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
# Load current IssuerDB module
|
|
|
|
|
unless ( $self->loadModule($module_name) ) {
|
2010-08-30 17:46:26 +02:00
|
|
|
|
$self->lmLog( "Unable to load $module_name",
|
|
|
|
|
'error' );
|
2010-09-01 14:56:15 +02:00
|
|
|
|
next;
|
|
|
|
|
}
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
2010-09-10 22:27:14 +02:00
|
|
|
|
$self->{error} = $self->_subProcess(
|
|
|
|
|
$module_name . "::issuerDBInit",
|
|
|
|
|
$module_name . '::issuerLogout'
|
|
|
|
|
);
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
}
|
2010-08-23 15:27:16 +02:00
|
|
|
|
}
|
2010-02-18 18:22:04 +01:00
|
|
|
|
|
2010-09-03 17:23:08 +02:00
|
|
|
|
# Call logout for the module used to authenticate
|
2013-01-11 18:11:37 +01:00
|
|
|
|
$self->lmLog(
|
2014-02-26 11:57:49 +01:00
|
|
|
|
"Process logout for authentication module "
|
|
|
|
|
. $self->{sessionInfo}->{_auth},
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
2013-01-11 18:11:37 +01:00
|
|
|
|
|
2015-03-09 17:44:19 +01:00
|
|
|
|
if ( $self->{sessionInfo}->{'_auth'} ne
|
|
|
|
|
$self->get_module('auth') )
|
2014-02-26 11:57:49 +01:00
|
|
|
|
{
|
|
|
|
|
my $module_name = 'Lemonldap::NG::Portal::Auth'
|
|
|
|
|
. $self->{sessionInfo}->{_auth};
|
2013-01-11 18:11:37 +01:00
|
|
|
|
|
|
|
|
|
unless ( $self->loadModule($module_name) ) {
|
|
|
|
|
$self->lmLog( "Unable to load $module_name", 'error' );
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
eval {
|
|
|
|
|
$self->{error} = $self->_subProcess(
|
|
|
|
|
$module_name . "::authInit",
|
|
|
|
|
$module_name . "::authLogout"
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2010-09-03 17:23:08 +02:00
|
|
|
|
eval {
|
|
|
|
|
$self->{error} =
|
2013-01-11 18:11:37 +01:00
|
|
|
|
$self->_subProcess( 'authInit', 'authLogout' );
|
2010-09-03 17:23:08 +02:00
|
|
|
|
};
|
|
|
|
|
}
|
2010-09-01 14:56:15 +02:00
|
|
|
|
if ($@) {
|
2013-01-11 18:11:37 +01:00
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Error when calling authentication logout: $@",
|
2010-08-30 17:46:26 +02:00
|
|
|
|
'debug' );
|
2010-09-01 14:56:15 +02:00
|
|
|
|
}
|
|
|
|
|
return $self->{error} if $self->{error} > 0;
|
2010-02-18 18:22:04 +01:00
|
|
|
|
|
2010-08-30 17:46:26 +02:00
|
|
|
|
# Collect logout services and build hidden iFrames
|
2015-12-16 21:44:27 +01:00
|
|
|
|
if ( $self->{logoutServices} and %{ $self->{logoutServices} } ) {
|
2010-08-30 17:46:26 +02:00
|
|
|
|
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Create iFrames to forward logout to services",
|
|
|
|
|
'debug' );
|
|
|
|
|
|
2012-02-15 12:58:32 +01:00
|
|
|
|
$self->info( "<h3>" . $self->msg(PM_LOGOUT) . "</h3>" );
|
2010-08-30 17:46:26 +02:00
|
|
|
|
|
|
|
|
|
foreach ( keys %{ $self->{logoutServices} } ) {
|
|
|
|
|
my $logoutServiceName = $_;
|
|
|
|
|
my $logoutServiceUrl =
|
|
|
|
|
$self->{logoutServices}->{$logoutServiceName};
|
|
|
|
|
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Find logout service $logoutServiceName ($logoutServiceUrl)",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
my $iframe =
|
|
|
|
|
"<iframe src=\"$logoutServiceUrl\""
|
|
|
|
|
. " alt=\"$logoutServiceName\" marginwidth=\"0\""
|
|
|
|
|
. " marginheight=\"0\" scrolling=\"no\" style=\"border: none;display: hidden;margin: 0\""
|
|
|
|
|
. " width=\"0\" height=\"0\" frameborder=\"0\">"
|
|
|
|
|
. "</iframe>";
|
|
|
|
|
|
|
|
|
|
$self->info($iframe);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Redirect on logout page if no other target defined
|
|
|
|
|
if ( !$self->{urldc} and !$self->{postUrl} ) {
|
|
|
|
|
$self->{urldc} = $ENV{SCRIPT_NAME} . "?logout=1";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
# Redirect or Post if asked by authLogout
|
2012-02-17 19:48:04 +01:00
|
|
|
|
return $self->_subProcess(qw(autoRedirect))
|
2010-09-03 15:21:03 +02:00
|
|
|
|
if ( $self->{urldc}
|
|
|
|
|
and $self->{urldc} ne $self->{portal} );
|
2012-02-17 19:48:04 +01:00
|
|
|
|
|
|
|
|
|
return $self->_subProcess(qw(autoPost))
|
|
|
|
|
if ( $self->{postUrl} );
|
2010-01-12 11:36:04 +01:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
# Display logout message
|
|
|
|
|
return PE_LOGOUT_OK;
|
|
|
|
|
}
|
2008-05-11 21:21:39 +02:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
# If the user wants to purge other sessions
|
|
|
|
|
elsif ( $self->param('removeOther') ) {
|
|
|
|
|
$self->{notifyDeleted} = 1;
|
|
|
|
|
$self->{singleSession} = 1;
|
|
|
|
|
$self->_sub( 'removeOther', $id );
|
|
|
|
|
}
|
2010-10-25 08:25:20 +02:00
|
|
|
|
|
|
|
|
|
# Special ajax request "ping" to check if session is available
|
|
|
|
|
if ( $self->param('ping') ) {
|
|
|
|
|
print $self->header( -type => 'application/json' )
|
|
|
|
|
. '{"auth":true}';
|
|
|
|
|
$self->quit();
|
|
|
|
|
}
|
2012-12-04 17:31:12 +01:00
|
|
|
|
|
|
|
|
|
# Special ajax request "storeAppsListOrder"
|
|
|
|
|
if ( $self->param('storeAppsListOrder') ) {
|
|
|
|
|
my $order = $self->param('storeAppsListOrder');
|
|
|
|
|
$self->lmLog( "Get new apps list order: $order", 'debug' );
|
|
|
|
|
$self->updatePersistentSession( { appsListOrder => $order } );
|
|
|
|
|
$self->quit();
|
|
|
|
|
}
|
2013-01-11 18:11:37 +01:00
|
|
|
|
|
2010-09-01 14:56:15 +02:00
|
|
|
|
$self->{id} = $id;
|
|
|
|
|
|
2010-09-13 17:14:19 +02:00
|
|
|
|
# A session has been found => call existingSession
|
2010-09-01 14:56:15 +02:00
|
|
|
|
my $r = $self->_sub( 'existingSession', $id, $self->{sessionInfo} );
|
|
|
|
|
if ( $r == PE_DONE ) {
|
|
|
|
|
$self->{error} = $self->_subProcess(
|
2014-06-25 13:53:09 +02:00
|
|
|
|
qw(checkNotification issuerDBInit authInit issuerForAuthUser authFinish autoRedirect)
|
2010-09-01 14:56:15 +02:00
|
|
|
|
);
|
|
|
|
|
return $self->{error} || PE_DONE;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return $r;
|
|
|
|
|
}
|
2007-02-11 09:31:56 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-30 17:46:26 +02:00
|
|
|
|
|
2014-06-10 18:21:33 +02:00
|
|
|
|
# Special ajax request "ping" to check if session is available
|
2010-10-25 08:25:20 +02:00
|
|
|
|
if ( $self->param('ping') ) {
|
|
|
|
|
print $self->header( -type => 'application/json' ) . '{"auth":false}';
|
|
|
|
|
$self->quit();
|
|
|
|
|
}
|
2014-06-10 18:21:33 +02:00
|
|
|
|
|
|
|
|
|
# Display logout success if logout asked
|
|
|
|
|
# and we do not have valid session
|
2010-08-30 17:46:26 +02:00
|
|
|
|
return PE_LOGOUT_OK if $self->param('logout');
|
|
|
|
|
|
|
|
|
|
# Else continue authentication process
|
2007-02-11 09:31:56 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
## @method int existingSession()
|
|
|
|
|
# Launched by controlExistingSession() to know what to do with existing
|
|
|
|
|
# sessions.
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Can return:
|
|
|
|
|
# - PE_DONE: session is unchanged and process() return true
|
|
|
|
|
# - PE_OK: process() return false to display the form
|
2009-02-17 15:56:38 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2007-02-11 09:31:56 +01:00
|
|
|
|
sub existingSession {
|
2010-01-25 18:40:46 +01:00
|
|
|
|
my $self = shift;
|
2010-02-28 20:07:02 +01:00
|
|
|
|
my $forceAuthn;
|
2010-01-25 18:40:46 +01:00
|
|
|
|
|
|
|
|
|
# Check portalForceAuthn parameter
|
2010-02-28 20:07:02 +01:00
|
|
|
|
# and authForce method
|
2010-09-13 17:14:19 +02:00
|
|
|
|
eval { $forceAuthn = $self->_sub('authForce'); };
|
2010-02-28 20:07:02 +01:00
|
|
|
|
if ($@) {
|
|
|
|
|
$self->lmLog( "Error when calling authForce: $@", 'debug' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$forceAuthn = 1 if ( $self->{portalForceAuthn} );
|
|
|
|
|
|
|
|
|
|
if ($forceAuthn) {
|
2010-01-25 18:40:46 +01:00
|
|
|
|
my $referer = $self->referer();
|
|
|
|
|
my $id = $self->{id};
|
|
|
|
|
|
2010-02-05 11:21:48 +01:00
|
|
|
|
# Do not force authentication when password is modified
|
|
|
|
|
return PE_DONE if $self->param('newpassword');
|
|
|
|
|
|
|
|
|
|
# Do not force authentication if last successful authentication is recent
|
|
|
|
|
my $last_authn_utime = $self->{sessionInfo}->{_lastAuthnUTime} || 0;
|
|
|
|
|
if ( time() - $last_authn_utime < $self->{portalForceAuthnInterval} ) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Authentication is recent, so do not force authentication for session $id",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
return PE_DONE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-27 15:04:41 +01:00
|
|
|
|
# If coming from the portal follow the normal process to update the session
|
2010-01-25 18:40:46 +01:00
|
|
|
|
if ( $referer ? ( $referer =~ m#$self->{portal}#i ) : 0 ) {
|
|
|
|
|
$self->lmLog( "Portal referer detected for session $id", 'debug' );
|
|
|
|
|
|
|
|
|
|
# Set flag to update session timestamp
|
|
|
|
|
$self->{updateSession} = 1;
|
|
|
|
|
|
|
|
|
|
# Process
|
|
|
|
|
$self->{error} = $self->_subProcess(
|
2010-07-02 17:14:54 +02:00
|
|
|
|
qw(issuerDBInit authInit issuerForUnAuthUser extractFormInfo
|
2010-01-27 15:04:41 +01:00
|
|
|
|
userDBInit getUser setAuthSessionInfo setSessionInfo
|
2012-02-09 10:01:04 +01:00
|
|
|
|
setMacros setGroups setPersistentSessionInfo
|
2014-06-25 13:53:09 +02:00
|
|
|
|
setLocalGroups authenticate authFinish userDBFinish store)
|
2010-01-25 18:40:46 +01:00
|
|
|
|
);
|
|
|
|
|
return $self->{error} || PE_DONE;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->lmLog( "Force reauthentication for session $id", 'debug' );
|
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Else return PE_DONE
|
2008-12-01 10:36:02 +01:00
|
|
|
|
PE_DONE;
|
2006-12-18 12:32:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# issuerDBInit(): must be implemented in IssuerDB* module
|
2008-11-20 19:13:27 +01:00
|
|
|
|
|
2010-01-28 15:47:51 +01:00
|
|
|
|
# authInit(): must be implemented in Auth* module
|
|
|
|
|
|
2010-07-02 17:42:22 +02:00
|
|
|
|
# issuerForUnAuthUser(): must be implemented in IssuerDB* module
|
|
|
|
|
|
2012-02-28 15:38:13 +01:00
|
|
|
|
##@apmethod int extractFormInfo()
|
|
|
|
|
# Extract data common to all authentication modules,
|
|
|
|
|
# and call extractFormInfo() in Auth* module
|
|
|
|
|
# Auth*::extractFormInfo set $self->{user} and in some cases
|
|
|
|
|
# authenticate user (done in authenticate() else)
|
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
|
|
|
|
sub extractFormInfo {
|
|
|
|
|
my $self = shift;
|
2012-09-08 19:20:08 +02:00
|
|
|
|
return PE_OK if $self->{skipExtractFormInfo};
|
2012-02-28 15:38:13 +01:00
|
|
|
|
$self->{checkLogins} = $self->param('checkLogins');
|
|
|
|
|
return $self->SUPER::extractFormInfo;
|
|
|
|
|
}
|
2010-01-28 15:47:51 +01:00
|
|
|
|
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# getUser(): must be implemented in UserDB* module
|
2009-05-14 18:19:49 +02:00
|
|
|
|
|
2010-01-27 17:30:19 +01:00
|
|
|
|
## @apmethod int setAuthSessionInfo()
|
|
|
|
|
# Set _auth
|
|
|
|
|
# call setAuthSessionInfo in Auth* module
|
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
|
|
|
|
sub setAuthSessionInfo {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
# Get the current authentication module
|
2010-03-15 10:53:56 +01:00
|
|
|
|
$self->{sessionInfo}->{_auth} = $self->get_module("auth");
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2010-01-27 17:30:19 +01:00
|
|
|
|
return $self->SUPER::setAuthSessionInfo();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
## @apmethod int passwordDBInit()
|
|
|
|
|
# Set _passwordDB
|
|
|
|
|
# call passwordDBInit in passwordDB* module
|
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub passwordDBInit {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
2010-01-28 15:47:51 +01:00
|
|
|
|
# Get the current password module
|
2010-03-15 10:53:56 +01:00
|
|
|
|
$self->{sessionInfo}->{_passwordDB} = $self->get_module("password");
|
2010-01-27 17:30:19 +01:00
|
|
|
|
|
|
|
|
|
return $self->SUPER::passwordDBInit();
|
|
|
|
|
}
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2011-06-29 14:47:25 +02:00
|
|
|
|
## @apmethod int modifyPassword()
|
|
|
|
|
# Call modifyPassword from PasswordDB* module
|
|
|
|
|
# Continue auth process if password change is ok
|
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub modifyPassword {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
my $res = $self->SUPER::modifyPassword();
|
|
|
|
|
|
|
|
|
|
if ( $res == PE_PASSWORD_OK ) {
|
|
|
|
|
|
2011-11-07 12:18:42 +01:00
|
|
|
|
# Update password in session if needed
|
|
|
|
|
$self->lmLog( "Update password in session for " . $self->{user},
|
|
|
|
|
'debug' );
|
|
|
|
|
|
|
|
|
|
my $infos;
|
|
|
|
|
$infos->{_password} = $self->{newpassword};
|
|
|
|
|
$self->updateSession($infos) if ( $self->{storePassword} );
|
|
|
|
|
|
2011-06-29 14:47:25 +02:00
|
|
|
|
# Set a flag to ignore password change in Menu
|
|
|
|
|
$self->{ignorePasswordChange} = 1;
|
|
|
|
|
|
2011-11-07 17:59:54 +01:00
|
|
|
|
# Set a flag to allow sending a mail
|
|
|
|
|
$self->{passwordWasChanged} = 1;
|
|
|
|
|
|
2011-11-07 12:18:42 +01:00
|
|
|
|
# Continue process if password change is ok
|
2011-06-29 14:47:25 +02:00
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $res;
|
|
|
|
|
}
|
2009-05-14 18:19:49 +02:00
|
|
|
|
|
2009-02-24 18:53:59 +01:00
|
|
|
|
##@apmethod int setSessionInfo()
|
2013-01-03 19:28:55 +01:00
|
|
|
|
# Set ipAddr, startTime, updateTime, _utime and _userDB
|
2010-01-27 17:30:19 +01:00
|
|
|
|
# Call setSessionInfo() in UserDB* module
|
2009-02-24 18:53:59 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
|
|
|
|
sub setSessionInfo {
|
|
|
|
|
my $self = shift;
|
2010-01-27 17:30:19 +01:00
|
|
|
|
|
2010-01-28 15:47:51 +01:00
|
|
|
|
# Get the current user module
|
2010-03-15 10:53:56 +01:00
|
|
|
|
$self->{sessionInfo}->{_userDB} = $self->get_module("user");
|
2009-02-24 18:53:59 +01:00
|
|
|
|
|
2012-06-26 18:05:27 +02:00
|
|
|
|
# Store IP address from remote address or X-FORWARDED-FOR header
|
2013-01-03 19:28:55 +01:00
|
|
|
|
$self->{sessionInfo}->{ipAddr} = $self->ipAddr;
|
2010-01-11 17:04:36 +01:00
|
|
|
|
|
2010-05-07 23:33:57 +02:00
|
|
|
|
# Date and time
|
2010-01-25 18:40:46 +01:00
|
|
|
|
if ( $self->{updateSession} ) {
|
|
|
|
|
$self->{sessionInfo}->{updateTime} =
|
2012-07-12 09:09:41 +02:00
|
|
|
|
strftime( "%Y%m%d%H%M%S", localtime() );
|
2010-01-25 18:40:46 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
2010-03-24 14:44:24 +01:00
|
|
|
|
$self->{sessionInfo}->{_utime} ||= time();
|
2010-03-01 21:32:28 +01:00
|
|
|
|
$self->{sessionInfo}->{startTime} =
|
2012-07-12 09:09:41 +02:00
|
|
|
|
strftime( "%Y%m%d%H%M%S", localtime() );
|
2010-01-25 18:40:46 +01:00
|
|
|
|
}
|
2010-05-07 23:33:57 +02:00
|
|
|
|
|
|
|
|
|
# Get environment variables matching exportedVars
|
|
|
|
|
foreach ( keys %{ $self->{exportedVars} } ) {
|
|
|
|
|
if ( my $tmp = $ENV{ $self->{exportedVars}->{$_} } ) {
|
|
|
|
|
$tmp =~ s/[\r\n]/ /gs;
|
|
|
|
|
$self->{sessionInfo}->{$_} = $tmp;
|
|
|
|
|
delete $self->{exportedVars}->{$_};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 11:51:20 +02:00
|
|
|
|
# Store URL origin in session
|
|
|
|
|
$self->{sessionInfo}->{_url} = $self->{urldc};
|
|
|
|
|
|
2010-05-07 23:33:57 +02:00
|
|
|
|
# Call UserDB setSessionInfo
|
2010-10-08 18:02:43 +02:00
|
|
|
|
if ( my $res = $self->SUPER::setSessionInfo() ) {
|
|
|
|
|
return $res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PE_OK;
|
2009-02-24 18:53:59 +01:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-07 11:27:36 +01:00
|
|
|
|
##@apmethod int setMacros()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Macro mechanism.
|
|
|
|
|
# * store macro results in $self->{sessionInfo}
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2007-01-13 20:34:03 +01:00
|
|
|
|
sub setMacros {
|
2011-02-07 11:27:36 +01:00
|
|
|
|
my $self = shift;
|
2013-05-21 11:34:01 +02:00
|
|
|
|
foreach ( sort keys %{ $self->{macros} } ) {
|
|
|
|
|
$self->{sessionInfo}->{$_} =
|
|
|
|
|
$self->safe->reval( $self->{macros}->{$_} );
|
2008-11-20 19:13:27 +01:00
|
|
|
|
}
|
2007-01-13 20:34:03 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-04 11:13:03 +02:00
|
|
|
|
##@apmethod int setLocalGroups()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Groups mechanism.
|
|
|
|
|
# * store all groups name that the user match in $self->{sessionInfo}->{groups}
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2009-06-04 11:13:03 +02:00
|
|
|
|
sub setLocalGroups {
|
2013-05-21 11:34:01 +02:00
|
|
|
|
my $self = shift;
|
|
|
|
|
foreach ( sort keys %{ $self->{groups} } ) {
|
2015-09-25 11:43:04 +02:00
|
|
|
|
if ( $self->safe->reval( $self->{groups}->{$_} ) ) {
|
|
|
|
|
$self->{sessionInfo}->{groups} .=
|
|
|
|
|
$self->{multiValuesSeparator} . $_;
|
|
|
|
|
$self->{sessionInfo}->{hGroups}->{$_}->{name} = $_;
|
|
|
|
|
}
|
2008-11-20 19:13:27 +01:00
|
|
|
|
}
|
2013-05-30 16:41:02 +02:00
|
|
|
|
|
2013-05-21 11:34:01 +02:00
|
|
|
|
# Clear values separator at the beginning
|
2012-06-20 10:41:31 +02:00
|
|
|
|
if ( $self->{sessionInfo}->{groups} ) {
|
|
|
|
|
$self->{sessionInfo}->{groups} =~
|
|
|
|
|
s/^\Q$self->{multiValuesSeparator}\E//;
|
|
|
|
|
}
|
2006-12-18 12:32:33 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# setGroups(): must be implemented in UserDB* module
|
2009-06-04 11:13:03 +02:00
|
|
|
|
|
2010-10-21 12:28:47 +02:00
|
|
|
|
##@apmethod int setPersistentSessionInfo()
|
|
|
|
|
# Restore persistent session info
|
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
|
|
|
|
sub setPersistentSessionInfo {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
# Do not restore infos if session already opened
|
|
|
|
|
unless ( $self->{id} ) {
|
2010-10-26 13:36:57 +02:00
|
|
|
|
my $key = $self->{sessionInfo}->{ $self->{whatToTrace} };
|
2011-06-09 16:30:50 +02:00
|
|
|
|
|
2010-10-26 13:36:57 +02:00
|
|
|
|
return PE_OK unless ( $key and length($key) );
|
2011-06-09 16:30:50 +02:00
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $persistentSession =
|
|
|
|
|
$self->getPersistentSession( $self->_md5hash($key) );
|
|
|
|
|
|
|
|
|
|
if ($persistentSession) {
|
2011-06-09 16:30:50 +02:00
|
|
|
|
$self->lmLog( "Persistent session found for $key", 'debug' );
|
2014-02-26 11:57:49 +01:00
|
|
|
|
foreach my $k ( keys %{ $persistentSession->data } ) {
|
2011-06-09 16:30:50 +02:00
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
# Do not restore some parameters
|
2015-12-19 07:56:59 +01:00
|
|
|
|
next if $k =~ /^_session_(?:u?id|kind)$/;
|
2011-06-09 16:30:50 +02:00
|
|
|
|
$self->lmLog( "Restore persistent parameter $k", 'debug' );
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$self->{sessionInfo}->{$k} = $persistentSession->data->{$k};
|
2010-10-21 12:28:47 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-07 17:59:54 +01:00
|
|
|
|
## @apmethod sendPasswordMail
|
|
|
|
|
# Call sendPasswordMail from MailReset if option is configured
|
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub sendPasswordMail {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
if ( $self->{mailOnPasswordChange} && $self->{passwordWasChanged} ) {
|
|
|
|
|
|
|
|
|
|
$self->lmLog( "Send password by mail requested", 'debug' );
|
|
|
|
|
|
|
|
|
|
eval "require Lemonldap::NG::Portal::MailReset";
|
|
|
|
|
&Lemonldap::NG::Portal::MailReset::smtpInit($self);
|
|
|
|
|
&Lemonldap::NG::Portal::MailReset::sendPasswordMail($self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Never stop the process here
|
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int authenticate()
|
2012-01-10 20:54:30 +01:00
|
|
|
|
# Call authenticate() in Auth* module, and registerLogin()
|
|
|
|
|
# if authentication failed, userNotice() if it succeeded.
|
2009-02-17 15:56:38 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2009-02-15 18:58:38 +01:00
|
|
|
|
sub authenticate {
|
|
|
|
|
my $self = shift;
|
2012-01-10 20:54:30 +01:00
|
|
|
|
if ( my $errorCode = $self->SUPER::authenticate() ) {
|
2012-01-12 18:30:06 +01:00
|
|
|
|
$self->registerLogin($errorCode);
|
|
|
|
|
return $errorCode;
|
2012-01-10 20:54:30 +01:00
|
|
|
|
}
|
2010-02-05 11:21:48 +01:00
|
|
|
|
|
|
|
|
|
# Log good authentication
|
2010-04-15 15:46:45 +02:00
|
|
|
|
my $user = $self->{sessionInfo}->{ $self->{whatToTrace} };
|
2012-03-21 16:35:43 +01:00
|
|
|
|
$self->_sub( 'userNotice',
|
|
|
|
|
"Good authentication for $user by $self->{sessionInfo}->{_auth}" )
|
|
|
|
|
if $user;
|
2010-02-05 11:21:48 +01:00
|
|
|
|
|
|
|
|
|
# Set _lastAuthnUTime
|
|
|
|
|
$self->{sessionInfo}->{_lastAuthnUTime} = time();
|
|
|
|
|
|
2009-02-15 18:58:38 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
2008-11-20 19:13:27 +01:00
|
|
|
|
|
2012-01-12 18:30:06 +01:00
|
|
|
|
##@method registerLogin
|
2012-01-10 20:54:30 +01:00
|
|
|
|
# Store current login in login history
|
|
|
|
|
# @param $errorCode Code returned by authenticate()
|
|
|
|
|
sub registerLogin {
|
|
|
|
|
my ( $self, $errorCode ) = @_;
|
|
|
|
|
|
2012-02-09 16:00:35 +01:00
|
|
|
|
if ( $self->{loginHistoryEnabled} ) {
|
2012-01-10 20:54:30 +01:00
|
|
|
|
my $history = $self->{sessionInfo}->{loginHistory} ||= {};
|
|
|
|
|
|
2012-01-12 18:30:06 +01:00
|
|
|
|
my $type = ( $errorCode ? "failed" : "success" ) . "Login";
|
2012-01-10 20:54:30 +01:00
|
|
|
|
$history->{$type} ||= [];
|
2012-01-12 18:30:06 +01:00
|
|
|
|
$self->lmLog( "Current login saved into $type", "debug" );
|
2012-01-10 20:54:30 +01:00
|
|
|
|
|
|
|
|
|
# Gather current login's parameters
|
|
|
|
|
my $login = $self->_sumUpSession( $self->{sessionInfo}, 1 );
|
2012-02-15 12:58:32 +01:00
|
|
|
|
$login->{error} = $self->error($errorCode)
|
2012-01-12 18:30:06 +01:00
|
|
|
|
if ($errorCode);
|
2012-01-10 20:54:30 +01:00
|
|
|
|
|
|
|
|
|
# Add current login into history
|
2012-01-12 18:30:06 +01:00
|
|
|
|
unshift @{ $history->{$type} }, $login;
|
2012-01-10 20:54:30 +01:00
|
|
|
|
|
|
|
|
|
# Forget oldest logins
|
2012-02-01 11:45:53 +01:00
|
|
|
|
splice @{ $history->{$type} }, $self->{ $type . "Number" }
|
|
|
|
|
if ( scalar @{ $history->{$type} } > $self->{ $type . "Number" } );
|
2012-01-10 20:54:30 +01:00
|
|
|
|
|
|
|
|
|
# Save into persistent session
|
2012-01-12 18:30:06 +01:00
|
|
|
|
$self->updatePersistentSession( { loginHistory => $history, } );
|
2012-01-10 20:54:30 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-10 18:03:57 +01:00
|
|
|
|
##@apmethod int removeOther()
|
|
|
|
|
# check singleSession or singleIP parameters, and remove other sessions if needed
|
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2009-10-21 14:43:13 +02:00
|
|
|
|
sub removeOther {
|
2010-01-12 11:36:04 +01:00
|
|
|
|
my ( $self, $current ) = @_;
|
2010-01-15 23:01:04 +01:00
|
|
|
|
$self->{deleted} = [];
|
2010-01-12 10:53:49 +01:00
|
|
|
|
$self->{otherSessions} = [];
|
2014-02-26 11:57:49 +01:00
|
|
|
|
|
|
|
|
|
my $moduleOptions = $self->{globalStorageOptions} || {};
|
|
|
|
|
$moduleOptions->{backend} = $self->{globalStorage};
|
|
|
|
|
my $module = "Lemonldap::NG::Common::Apache::Session";
|
|
|
|
|
|
2010-09-03 15:21:03 +02:00
|
|
|
|
if ( $self->{singleSession}
|
|
|
|
|
or $self->{singleIP}
|
|
|
|
|
or $self->{notifyOther} )
|
|
|
|
|
{
|
2009-11-09 16:32:27 +01:00
|
|
|
|
my $sessions =
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$module->searchOn( $moduleOptions, $self->{whatToTrace},
|
2009-11-09 16:32:27 +01:00
|
|
|
|
$self->{sessionInfo}->{ $self->{whatToTrace} } );
|
2009-10-21 14:43:13 +02:00
|
|
|
|
foreach my $id ( keys %$sessions ) {
|
2010-01-12 11:36:04 +01:00
|
|
|
|
next if ( $current and ( $current eq $id ) );
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $session = $self->getApacheSession( $id, 1 ) or next;
|
2010-01-12 10:53:49 +01:00
|
|
|
|
if (
|
|
|
|
|
$self->{singleSession}
|
|
|
|
|
or ( $self->{singleIP}
|
2014-02-26 11:57:49 +01:00
|
|
|
|
and $self->{sessionInfo}->{ipAddr} ne
|
|
|
|
|
$session->data->{ipAddr} )
|
2010-01-12 10:53:49 +01:00
|
|
|
|
)
|
2009-11-09 16:32:27 +01:00
|
|
|
|
{
|
2014-02-26 11:57:49 +01:00
|
|
|
|
push @{ $self->{deleted} },
|
|
|
|
|
$self->_sumUpSession( $session->data );
|
|
|
|
|
$self->_deleteSession( $session, 1 );
|
2010-01-12 10:53:49 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
2014-02-26 11:57:49 +01:00
|
|
|
|
push @{ $self->{otherSessions} },
|
|
|
|
|
$self->_sumUpSession( $session->data );
|
2009-11-25 13:38:22 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( $self->{singleUserByIP} ) {
|
|
|
|
|
my $sessions =
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$module->searchOn( $moduleOptions, 'ipAddr', $self->ipAddr );
|
2009-11-25 13:38:22 +01:00
|
|
|
|
foreach my $id ( keys %$sessions ) {
|
2010-01-12 11:36:04 +01:00
|
|
|
|
next if ( $current and $current eq $id );
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $session = $self->getApacheSession( $id, 1 ) or next;
|
2009-12-11 22:17:06 +01:00
|
|
|
|
unless ( $self->{sessionInfo}->{ $self->{whatToTrace} } eq
|
2014-02-26 11:57:49 +01:00
|
|
|
|
$session->data->{ $self->{whatToTrace} } )
|
2009-11-25 13:38:22 +01:00
|
|
|
|
{
|
2014-02-26 11:57:49 +01:00
|
|
|
|
push @{ $self->{deleted} },
|
|
|
|
|
$self->_sumUpSession( $session->data );
|
|
|
|
|
$self->_deleteSession( $session, 1 );
|
2010-01-11 17:04:36 +01:00
|
|
|
|
}
|
2009-10-21 14:43:13 +02:00
|
|
|
|
}
|
2010-01-15 23:01:04 +01:00
|
|
|
|
}
|
2010-01-12 10:53:49 +01:00
|
|
|
|
$self->info(
|
2012-01-10 20:54:30 +01:00
|
|
|
|
$self->mkSessionArray(
|
2012-02-27 22:27:52 +01:00
|
|
|
|
$self->{deleted}, $self->msg(PM_SESSIONS_DELETED), 1
|
|
|
|
|
)
|
2010-01-12 10:53:49 +01:00
|
|
|
|
) if ( $self->{notifyDeleted} and @{ $self->{deleted} } );
|
|
|
|
|
$self->info(
|
2012-02-27 22:27:52 +01:00
|
|
|
|
$self->mkSessionArray( $self->{otherSessions},
|
|
|
|
|
$self->msg(PM_OTHER_SESSIONS), 1 )
|
2012-01-12 18:30:06 +01:00
|
|
|
|
. $self->_mkRemoveOtherLink()
|
2010-01-12 10:53:49 +01:00
|
|
|
|
) if ( $self->{notifyOther} and @{ $self->{otherSessions} } );
|
2012-02-27 21:16:09 +01:00
|
|
|
|
|
|
|
|
|
$self->info(
|
|
|
|
|
(
|
|
|
|
|
$self->{sessionInfo}->{loginHistory}->{successLogin}
|
|
|
|
|
? $self->mkSessionArray(
|
2012-02-27 22:27:52 +01:00
|
|
|
|
$self->{sessionInfo}->{loginHistory}->{successLogin},
|
|
|
|
|
$self->msg(PM_LAST_LOGINS),
|
|
|
|
|
0, 0
|
|
|
|
|
)
|
2012-02-27 21:16:09 +01:00
|
|
|
|
: ""
|
2012-02-27 22:27:52 +01:00
|
|
|
|
)
|
|
|
|
|
. (
|
2012-02-27 21:16:09 +01:00
|
|
|
|
$self->{sessionInfo}->{loginHistory}->{failedLogin}
|
|
|
|
|
? $self->mkSessionArray(
|
2012-02-27 22:27:52 +01:00
|
|
|
|
$self->{sessionInfo}->{loginHistory}->{failedLogin},
|
|
|
|
|
$self->msg(PM_LAST_FAILED_LOGINS),
|
|
|
|
|
0, 1
|
|
|
|
|
)
|
2012-02-27 21:16:09 +01:00
|
|
|
|
: ""
|
|
|
|
|
)
|
2012-02-28 15:38:13 +01:00
|
|
|
|
) if ( $self->{checkLogins} );
|
2012-02-27 21:16:09 +01:00
|
|
|
|
|
2010-01-12 10:53:49 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 11:57:49 +01:00
|
|
|
|
##@method private hashref _sumUpSession(Lemonldap::NG::Common::Session session)
|
2012-01-10 20:54:30 +01:00
|
|
|
|
# put main session data into a hash ref
|
|
|
|
|
# @param hashref $session The session to sum up
|
|
|
|
|
# @return hashref
|
|
|
|
|
sub _sumUpSession {
|
2012-01-12 18:30:06 +01:00
|
|
|
|
my ( $self, $session, $withoutUser ) = @_;
|
|
|
|
|
my $res =
|
|
|
|
|
$withoutUser
|
|
|
|
|
? {}
|
|
|
|
|
: { user => $session->{ $self->{whatToTrace} } };
|
2012-01-10 20:54:30 +01:00
|
|
|
|
$res->{$_} = $session->{$_}
|
2012-02-09 16:00:35 +01:00
|
|
|
|
foreach ( "_utime", "ipAddr", keys %{ $self->{sessionDataToRemember} } );
|
2012-01-10 20:54:30 +01:00
|
|
|
|
return $res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
##@method private string mkSessionArray(string title,array datas)
|
|
|
|
|
# Build an HTML array to display sessions
|
|
|
|
|
# @param $sessions Array ref of hash ref containing sessions datas
|
2010-01-12 10:53:49 +01:00
|
|
|
|
# @param $title Title of the array
|
2012-01-10 20:54:30 +01:00
|
|
|
|
# @param $displayUser To display "User" column
|
|
|
|
|
# @param $displaError To display "Error" column
|
2010-01-12 10:53:49 +01:00
|
|
|
|
# @return HTML string
|
2012-01-10 20:54:30 +01:00
|
|
|
|
sub mkSessionArray {
|
|
|
|
|
my ( $self, $sessions, $title, $displayUser, $displayError ) = @_;
|
|
|
|
|
|
2012-01-19 15:35:23 +01:00
|
|
|
|
return "" unless ( ref $sessions eq "ARRAY" and @$sessions );
|
2012-01-10 20:54:30 +01:00
|
|
|
|
|
2012-01-12 18:30:06 +01:00
|
|
|
|
my $tmp = $title ? "<h3>$title</h3>" : "";
|
2012-01-10 20:54:30 +01:00
|
|
|
|
$tmp .= "<table class=\"info\"><tbody>";
|
|
|
|
|
|
|
|
|
|
$tmp .= "<tr>";
|
2012-02-15 12:58:32 +01:00
|
|
|
|
$tmp .= "<th>" . $self->msg(PM_USER) . "</th>"
|
2012-01-12 18:30:06 +01:00
|
|
|
|
if ($displayUser);
|
2012-02-15 12:58:32 +01:00
|
|
|
|
$tmp .= "<th>" . $self->msg(PM_DATE) . "</th>";
|
|
|
|
|
$tmp .= "<th>" . $self->msg(PM_IP) . "</th>";
|
2012-02-09 16:00:35 +01:00
|
|
|
|
$tmp .= "<th>" . $self->{sessionDataToRemember}->{$_} . "</th>"
|
|
|
|
|
foreach ( keys %{ $self->{sessionDataToRemember} } );
|
2012-02-15 12:58:32 +01:00
|
|
|
|
$tmp .= '<th>' . $self->msg(PM_ERROR_MSG) . '</th>'
|
2012-01-12 18:30:06 +01:00
|
|
|
|
if ($displayError);
|
2010-01-15 23:01:04 +01:00
|
|
|
|
$tmp .= '</tr>';
|
2012-01-10 20:54:30 +01:00
|
|
|
|
|
|
|
|
|
foreach my $session (@$sessions) {
|
|
|
|
|
$tmp .= "<tr>";
|
|
|
|
|
$tmp .= "<td>$session->{user}</td>" if ($displayUser);
|
2012-01-12 18:30:06 +01:00
|
|
|
|
$tmp .=
|
2012-08-15 11:36:39 +02:00
|
|
|
|
"<td><script type=\"text/javascript\">var _date=new Date($session->{_utime}*1000);document.write(_date.toLocaleString());</script></td>";
|
2012-01-10 20:54:30 +01:00
|
|
|
|
$tmp .= "<td>$session->{ipAddr}</td>";
|
2012-02-09 22:56:24 +01:00
|
|
|
|
$tmp .= "<td>" . ( $session->{$_} || "" ) . "</td>"
|
2012-02-09 16:00:35 +01:00
|
|
|
|
foreach ( keys %{ $self->{sessionDataToRemember} } );
|
2012-01-10 20:54:30 +01:00
|
|
|
|
$tmp .= "<td>$session->{error}</td>" if ($displayError);
|
|
|
|
|
$tmp .= "</tr>";
|
2010-01-15 23:01:04 +01:00
|
|
|
|
}
|
|
|
|
|
$tmp .= '</tbody></table>';
|
2010-01-12 10:53:49 +01:00
|
|
|
|
return $tmp;
|
2009-10-21 14:43:13 +02:00
|
|
|
|
}
|
2010-01-12 10:53:49 +01:00
|
|
|
|
|
2010-08-20 15:48:09 +02:00
|
|
|
|
## @method private string _mkRemoveOtherLink()
|
|
|
|
|
# Build the removeOther link
|
2010-08-20 17:07:55 +02:00
|
|
|
|
# Last part of URL is built trough javascript
|
2010-08-20 15:48:09 +02:00
|
|
|
|
# @return removeOther link in HTML code
|
|
|
|
|
sub _mkRemoveOtherLink {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
2010-08-20 17:07:55 +02:00
|
|
|
|
my $link = $self->{portal} . "?removeOther=1";
|
2010-08-20 15:48:09 +02:00
|
|
|
|
|
2010-09-28 18:26:35 +02:00
|
|
|
|
return
|
|
|
|
|
"<p class=\"removeOther\"><a href=\"$link\" onclick=\"_go=0\">"
|
2012-02-15 12:58:32 +01:00
|
|
|
|
. $self->msg(PM_REMOVE_OTHER_SESSIONS)
|
2010-08-20 15:48:09 +02:00
|
|
|
|
. "</a></p>";
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-11 15:02:43 +01:00
|
|
|
|
##@apmethod int grantSession()
|
|
|
|
|
# Check grantSessionRule to allow session creation.
|
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
|
|
|
|
sub grantSession {
|
|
|
|
|
my ($self) = @_;
|
|
|
|
|
|
2012-01-12 18:30:06 +01:00
|
|
|
|
if ( defined $self->{grantSessionRule} ) {
|
|
|
|
|
|
2012-01-10 20:54:30 +01:00
|
|
|
|
# Eval grantSessionRule
|
2012-01-12 18:30:06 +01:00
|
|
|
|
# Kept for backward compatibility with LL::NG 1.1.2 and previous
|
2012-01-10 20:54:30 +01:00
|
|
|
|
my $grantSessionRule = $self->{grantSessionRule};
|
2012-01-12 18:30:06 +01:00
|
|
|
|
|
2012-01-10 20:54:30 +01:00
|
|
|
|
unless ( $self->safe->reval($grantSessionRule) ) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"User " . $self->{user} . " was not granted to open session",
|
|
|
|
|
'error' );
|
2012-01-12 18:30:06 +01:00
|
|
|
|
$self->registerLogin(PE_SESSIONNOTGRANTED);
|
|
|
|
|
return PE_SESSIONNOTGRANTED;
|
2012-01-10 20:54:30 +01:00
|
|
|
|
}
|
2010-01-11 15:02:43 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-12 18:30:06 +01:00
|
|
|
|
# Eval grantSessionRules sorted by comments
|
|
|
|
|
sub sortByComment {
|
|
|
|
|
my $A = ( $a =~ /^.*?##(.*)$/ )[0];
|
|
|
|
|
my $B = ( $b =~ /^.*?##(.*)$/ )[0];
|
|
|
|
|
return !$A ? 1 : !$B ? -1 : $A cmp $B;
|
|
|
|
|
}
|
|
|
|
|
foreach ( sort sortByComment keys %{ $self->{grantSessionRules} } ) {
|
2012-01-26 16:12:09 +01:00
|
|
|
|
$self->lmLog( "Grant session condition \"$_\" checked", "debug" );
|
2012-01-12 18:30:06 +01:00
|
|
|
|
unless ( $self->safe->reval($_) ) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"User " . $self->{user} . " was not granted to open session",
|
|
|
|
|
'error' );
|
|
|
|
|
my $msg = $self->safe->reval( $self->{grantSessionRules}->{$_} );
|
|
|
|
|
$msg = $self->{grantSessionRules}->{$_} if ($@);
|
|
|
|
|
$self->{ "error_" . PE_SESSIONNOTGRANTED } = $msg if ($msg);
|
|
|
|
|
$self->registerLogin(PE_SESSIONNOTGRANTED);
|
|
|
|
|
return PE_SESSIONNOTGRANTED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 17:01:13 +01:00
|
|
|
|
my $user = $self->{sessionInfo}->{ $self->{whatToTrace} };
|
|
|
|
|
$self->_sub( 'userNotice', "Session granted for $user" ) if ($user);
|
2012-01-12 18:30:06 +01:00
|
|
|
|
$self->registerLogin(PE_OK);
|
|
|
|
|
return PE_OK;
|
2010-01-11 15:02:43 +01:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int store()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Store user's datas in sessions database.
|
|
|
|
|
# Now, the user is known, authenticated and session variable are evaluated.
|
|
|
|
|
# It's time to store his parameters with Apache::Session::* module
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub store {
|
|
|
|
|
my ($self) = @_;
|
2009-02-14 09:55:19 +01:00
|
|
|
|
|
|
|
|
|
# Now, user is authenticated => inform Apache
|
|
|
|
|
$self->setApacheUser( $self->{sessionInfo}->{ $self->{whatToTrace} } );
|
2010-01-25 18:40:46 +01:00
|
|
|
|
|
|
|
|
|
# Create second session for unsecure cookie
|
2009-03-31 12:52:43 +02:00
|
|
|
|
if ( $self->{securedCookie} == 2 ) {
|
2014-02-26 11:57:49 +01:00
|
|
|
|
my $session2 = $self->getApacheSession( undef, 1 );
|
|
|
|
|
|
|
|
|
|
my %infos = %{ $self->{sessionInfo} };
|
|
|
|
|
$infos{_httpSessionType} = 1;
|
|
|
|
|
|
|
|
|
|
$session2->update( \%infos );
|
|
|
|
|
|
|
|
|
|
$self->{sessionInfo}->{_httpSession} = $session2->id;
|
2009-03-31 12:52:43 +02:00
|
|
|
|
}
|
2010-01-25 18:40:46 +01:00
|
|
|
|
|
|
|
|
|
# Main session
|
2014-06-25 12:01:17 +02:00
|
|
|
|
my $session = $self->getApacheSession( $self->{id}, 0, $self->{force} );
|
2014-10-27 12:19:25 +01:00
|
|
|
|
return PE_APACHESESSIONERROR unless ($session);
|
2014-02-07 11:17:45 +01:00
|
|
|
|
|
2014-01-31 15:11:39 +01:00
|
|
|
|
# Compute unsecure cookie value if needed
|
|
|
|
|
if ( $self->{securedCookie} == 3 ) {
|
|
|
|
|
$self->{sessionInfo}->{_httpSession} =
|
|
|
|
|
$self->{cipher}->encryptHex( $self->{id}, "http" );
|
|
|
|
|
}
|
2014-02-26 11:57:49 +01:00
|
|
|
|
|
2014-02-26 18:10:39 +01:00
|
|
|
|
# Fill session
|
|
|
|
|
my $infos = {};
|
2010-10-08 18:02:43 +02:00
|
|
|
|
foreach my $k ( keys %{ $self->{sessionInfo} } ) {
|
|
|
|
|
next unless defined $self->{sessionInfo}->{$k};
|
2013-10-08 16:16:46 +02:00
|
|
|
|
my $displayValue = $self->{sessionInfo}->{$k};
|
|
|
|
|
if ( $self->{hiddenAttributes} =~ /\b$k\b/ ) {
|
|
|
|
|
$displayValue = '****';
|
|
|
|
|
}
|
|
|
|
|
$self->lmLog( "Store $displayValue in session key $k", 'debug' );
|
2015-09-25 17:29:57 +02:00
|
|
|
|
$self->_dump($displayValue) if ref($displayValue);
|
2014-02-26 18:10:39 +01:00
|
|
|
|
$infos->{$k} = $self->{sessionInfo}->{$k};
|
2010-04-15 15:46:45 +02:00
|
|
|
|
}
|
2014-02-26 18:10:39 +01:00
|
|
|
|
$session->update($infos);
|
2010-01-25 18:40:46 +01:00
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-17 18:02:21 +02:00
|
|
|
|
## @apmethod int authFinish
|
|
|
|
|
# Call authFinish method from authentication module
|
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub authFinish {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
2015-03-09 17:44:19 +01:00
|
|
|
|
# Remove captcha session
|
|
|
|
|
if ( $self->{captcha_check_code} ) {
|
|
|
|
|
$self->removeCaptcha( $self->{captcha_check_code} );
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-17 18:02:21 +02:00
|
|
|
|
eval { $self->{error} = $self->SUPER::authFinish; };
|
|
|
|
|
if ($@) {
|
|
|
|
|
$self->lmLog(
|
2010-05-19 16:59:43 +02:00
|
|
|
|
"Optional authFinish method not defined in current authentication module: $@",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
2010-05-17 18:02:21 +02:00
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $self->{error};
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-25 13:53:09 +02:00
|
|
|
|
## @apmethod int userDBFinish
|
|
|
|
|
# Call userDBFinish method from userDB module
|
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub userDBFinish {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
eval { $self->{error} = $self->SUPER::userDBFinish; };
|
|
|
|
|
if ($@) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Optional userDBFinish method not defined in current userDB module: $@",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $self->{error};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
## @apmethod int passwordDBFinish
|
|
|
|
|
# Call passwordDBFinish method from passwordDB module
|
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub passwordDBFinish {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
|
|
eval { $self->{error} = $self->SUPER::passwordDBFinish; };
|
|
|
|
|
if ($@) {
|
|
|
|
|
$self->lmLog(
|
|
|
|
|
"Optional passwordDBFinish method not defined in current passwordDB module: $@",
|
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $self->{error};
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int buildCookie()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Build the Lemonldap::NG cookie.
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub buildCookie {
|
|
|
|
|
my $self = shift;
|
2008-08-08 18:19:16 +02:00
|
|
|
|
push @{ $self->{cookie} },
|
|
|
|
|
$self->cookie(
|
2009-08-20 16:19:40 +02:00
|
|
|
|
-name => $self->{cookieName},
|
|
|
|
|
-value => $self->{id},
|
|
|
|
|
-domain => $self->{domain},
|
|
|
|
|
-path => "/",
|
|
|
|
|
-secure => $self->{securedCookie},
|
|
|
|
|
-httponly => $self->{httpOnly},
|
2009-12-03 12:47:50 +01:00
|
|
|
|
-expires => $self->{cookieExpiration},
|
2006-12-18 12:32:33 +01:00
|
|
|
|
@_,
|
2008-08-08 18:19:16 +02:00
|
|
|
|
);
|
2012-02-07 17:18:46 +01:00
|
|
|
|
if ( $self->{securedCookie} >= 2 ) {
|
2009-03-31 12:52:43 +02:00
|
|
|
|
push @{ $self->{cookie} },
|
|
|
|
|
$self->cookie(
|
2014-02-07 11:17:45 +01:00
|
|
|
|
-name => $self->{cookieName} . "http",
|
|
|
|
|
-value => $self->{sessionInfo}->{_httpSession},
|
2009-08-20 16:19:40 +02:00
|
|
|
|
-domain => $self->{domain},
|
|
|
|
|
-path => "/",
|
|
|
|
|
-secure => 0,
|
|
|
|
|
-httponly => $self->{httpOnly},
|
2009-12-03 12:47:50 +01:00
|
|
|
|
-expires => $self->{cookieExpiration},
|
2009-03-31 12:52:43 +02:00
|
|
|
|
@_,
|
|
|
|
|
);
|
|
|
|
|
}
|
2006-12-18 12:32:33 +01:00
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int checkNotification()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# Check if messages has to be notified.
|
2012-07-12 23:04:06 +02:00
|
|
|
|
# Call Lemonldap::NG::Common::Notification::getNotification().
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2008-11-24 07:57:18 +01:00
|
|
|
|
sub checkNotification {
|
|
|
|
|
my $self = shift;
|
2009-01-30 16:26:34 +01:00
|
|
|
|
if ( $self->{notification}
|
2010-01-11 17:04:36 +01:00
|
|
|
|
and $self->{_notification} ||=
|
2009-01-30 16:26:34 +01:00
|
|
|
|
$self->{notifObject}->getNotification($self) )
|
|
|
|
|
{
|
|
|
|
|
return PE_NOTIFICATION;
|
2008-11-24 07:57:18 +01:00
|
|
|
|
}
|
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-19 16:59:43 +02:00
|
|
|
|
## @apmethod int issuerForAuthUser()
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# Check IssuerDB activation rule
|
|
|
|
|
# Register used module in user session
|
2010-05-19 16:59:43 +02:00
|
|
|
|
# @return Lemonldap::NG::Portal constant
|
|
|
|
|
sub issuerForAuthUser {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# User information
|
2012-02-29 17:01:13 +01:00
|
|
|
|
my $user = $self->{sessionInfo}->{ $self->{whatToTrace} } || 'unknown';
|
2010-05-19 16:59:43 +02:00
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# Get active module
|
|
|
|
|
my $issuerDBtype = $self->get_module('issuer');
|
2010-05-19 16:59:43 +02:00
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
# Eval activation rule
|
|
|
|
|
my $rule = $self->{ 'issuerDB' . $issuerDBtype . 'Rule' };
|
|
|
|
|
|
|
|
|
|
if ( defined $rule ) {
|
2010-05-19 16:59:43 +02:00
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
$self->lmLog( "Applying rule: $rule", 'debug' );
|
|
|
|
|
|
|
|
|
|
unless ( $self->safe->reval($rule) ) {
|
2010-08-30 15:41:45 +02:00
|
|
|
|
$self->lmLog(
|
2012-02-29 17:01:13 +01:00
|
|
|
|
"User $user was not allowed to use IssuerDB $issuerDBtype",
|
2012-03-09 13:41:17 +01:00
|
|
|
|
'warn' );
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
2010-08-30 15:41:45 +02:00
|
|
|
|
return PE_OK;
|
|
|
|
|
}
|
2010-05-19 16:59:43 +02:00
|
|
|
|
|
2010-08-23 15:27:16 +02:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$self->lmLog( "No rule found for IssuerDB $issuerDBtype", 'debug' );
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 13:41:17 +01:00
|
|
|
|
$self->lmLog( "User $user allowed to use IssuerDB $issuerDBtype", 'debug' );
|
2010-08-23 15:27:16 +02:00
|
|
|
|
|
|
|
|
|
# Register IssuerDB module in session
|
|
|
|
|
$self->addSessionValue( '_issuerDB', $issuerDBtype, $self->{id} );
|
2010-05-19 16:59:43 +02:00
|
|
|
|
|
|
|
|
|
# Call IssuerDB module method
|
|
|
|
|
return $self->SUPER::issuerForAuthUser();
|
|
|
|
|
}
|
2009-12-10 18:03:57 +01:00
|
|
|
|
|
2009-02-17 15:56:38 +01:00
|
|
|
|
##@apmethod int autoRedirect()
|
2009-12-10 18:03:57 +01:00
|
|
|
|
# If the user was redirected to the portal, we will now redirect him
|
|
|
|
|
# to the requested URL.
|
2008-12-28 09:36:52 +01:00
|
|
|
|
#@return Lemonldap::NG::Portal constant
|
2006-12-18 12:32:33 +01:00
|
|
|
|
sub autoRedirect {
|
|
|
|
|
my $self = shift;
|
2012-05-22 18:23:40 +02:00
|
|
|
|
$self->clearHiddenFormValue();
|
2009-02-12 18:09:33 +01:00
|
|
|
|
|
2010-09-16 17:10:00 +02:00
|
|
|
|
# Default redirection URL
|
2010-01-12 10:53:49 +01:00
|
|
|
|
$self->{urldc} ||= $self->{portal}
|
|
|
|
|
if ( $self->{mustRedirect} or $self->info() );
|
2010-01-11 17:04:36 +01:00
|
|
|
|
|
|
|
|
|
# Display info before redirecting
|
2010-08-20 12:31:20 +02:00
|
|
|
|
if ( $self->info() ) {
|
2010-08-20 17:07:55 +02:00
|
|
|
|
$self->{infoFormMethod} = $self->param('method') || "get";
|
2010-08-20 12:52:52 +02:00
|
|
|
|
$self->clearHiddenFormValue();
|
2010-08-20 12:31:20 +02:00
|
|
|
|
my ($query_string) = ( $self->{urldc} =~ /.+?\?(.+)/ );
|
|
|
|
|
if ($query_string) {
|
|
|
|
|
$self->lmLog(
|
2012-02-01 11:20:50 +01:00
|
|
|
|
"Transform query string $query_string into hidden form values",
|
2010-08-20 12:31:20 +02:00
|
|
|
|
'debug'
|
|
|
|
|
);
|
|
|
|
|
my $query = CGI->new($query_string);
|
|
|
|
|
my $formFields = $query->Vars;
|
|
|
|
|
foreach ( keys %$formFields ) {
|
|
|
|
|
$self->setHiddenFormValue( $_, $formFields->{$_}, "", 0 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return PE_INFO;
|
|
|
|
|
}
|
2009-02-23 18:35:38 +01:00
|
|
|
|
|
2009-02-12 18:09:33 +01:00
|
|
|
|
# Redirection should be made if
|
|
|
|
|
# - urldc defined
|
2010-01-15 23:01:04 +01:00
|
|
|
|
if ( $self->{urldc} ) {
|
2009-02-17 16:39:14 +01:00
|
|
|
|
|
2009-02-23 18:35:38 +01:00
|
|
|
|
# Cross-domain mechanism
|
2009-06-15 16:13:09 +02:00
|
|
|
|
if ( $self->{cda}
|
2009-02-17 16:39:14 +01:00
|
|
|
|
and $self->{id}
|
2012-05-23 20:46:38 +02:00
|
|
|
|
and $self->{urldc} !~ m#^https?://[^/]*$self->{domain}(:\d+)?/#oi
|
|
|
|
|
and $self->isTrustedUrl( $self->{urldc} ) )
|
2009-02-17 16:39:14 +01:00
|
|
|
|
{
|
2012-05-23 20:46:38 +02:00
|
|
|
|
my $ssl = $self->{urldc} =~ /^https/;
|
2009-02-17 16:39:14 +01:00
|
|
|
|
$self->lmLog( 'CDA request', 'debug' );
|
2012-06-12 17:46:18 +02:00
|
|
|
|
$self->{urldc} .= ( $self->{urldc} =~ /\?/ ? '&' : '?' )
|
|
|
|
|
. (
|
2012-09-07 17:43:07 +02:00
|
|
|
|
( $self->{securedCookie} < 2 or $ssl )
|
2012-06-12 17:46:18 +02:00
|
|
|
|
? $self->{cookieName} . "=" . $self->{id}
|
|
|
|
|
: $self->{cookieName} . "http="
|
|
|
|
|
. $self->{sessionInfo}->{_httpSession}
|
2010-06-21 17:29:59 +02:00
|
|
|
|
);
|
2009-02-17 16:39:14 +01:00
|
|
|
|
}
|
2012-02-01 11:20:50 +01:00
|
|
|
|
|
2008-05-11 21:21:39 +02:00
|
|
|
|
$self->updateStatus;
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2012-02-01 11:20:50 +01:00
|
|
|
|
if ( $self->safe->reval( $self->{jsRedirect} ) ) {
|
2012-03-14 20:14:17 +01:00
|
|
|
|
$self->{redirectFormMethod} = "get";
|
2012-02-01 15:18:41 +01:00
|
|
|
|
return PE_REDIRECT;
|
2012-02-01 11:20:50 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
2012-02-07 17:26:20 +01:00
|
|
|
|
print $self->redirect(
|
2012-02-01 11:20:50 +01:00
|
|
|
|
-status => '303 See Other',
|
|
|
|
|
-location => $self->{urldc},
|
|
|
|
|
);
|
|
|
|
|
$self->quit();
|
|
|
|
|
}
|
2006-12-18 12:32:33 +01:00
|
|
|
|
}
|
|
|
|
|
PE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-19 12:33:34 +01:00
|
|
|
|
## @method void returnSOAPMessage()
|
|
|
|
|
# Print SOAP message
|
|
|
|
|
# @return void
|
|
|
|
|
sub returnSOAPMessage {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
2010-06-02 11:12:35 +02:00
|
|
|
|
# Quit if no SOAP message
|
|
|
|
|
$self->quit() unless $self->{SOAPMessage};
|
2010-02-19 12:33:34 +01:00
|
|
|
|
|
|
|
|
|
# Print HTTP header and SOAP message
|
2010-08-31 12:34:28 +02:00
|
|
|
|
binmode( STDOUT, ":bytes" );
|
2010-02-22 11:08:14 +01:00
|
|
|
|
print $self->header( -type => 'application/xml' );
|
2010-02-19 12:33:34 +01:00
|
|
|
|
print $self->{SOAPMessage};
|
|
|
|
|
|
|
|
|
|
# Exit
|
|
|
|
|
$self->quit();
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 12:07:48 +01:00
|
|
|
|
## @method void autoPost()
|
|
|
|
|
# Transfer POST data with auto submit
|
|
|
|
|
# @return void
|
|
|
|
|
sub autoPost {
|
|
|
|
|
my $self = shift;
|
|
|
|
|
|
2010-08-20 12:31:20 +02:00
|
|
|
|
# Get URL and Form fields
|
2012-02-01 15:18:41 +01:00
|
|
|
|
$self->{urldc} = $self->{postUrl};
|
2010-08-20 12:31:20 +02:00
|
|
|
|
my $formFields = $self->{postFields};
|
|
|
|
|
|
2012-02-01 15:18:41 +01:00
|
|
|
|
$self->clearHiddenFormValue();
|
|
|
|
|
foreach ( keys %$formFields ) {
|
|
|
|
|
$self->setHiddenFormValue( $_, $formFields->{$_}, "", 0 );
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-19 18:19:30 +02:00
|
|
|
|
# Display info before redirecting
|
|
|
|
|
if ( $self->info() ) {
|
2010-08-20 17:07:55 +02:00
|
|
|
|
$self->{infoFormMethod} = $self->param('method') || "post";
|
2010-08-19 18:19:30 +02:00
|
|
|
|
return PE_INFO;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-14 20:14:17 +01:00
|
|
|
|
$self->{redirectFormMethod} = "post";
|
2012-02-01 15:18:41 +01:00
|
|
|
|
return PE_REDIRECT;
|
2010-02-22 12:07:48 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-09 13:41:17 +01:00
|
|
|
|
## @method HASHREF getCustomTemplateParameters()
|
|
|
|
|
# Find custom templates parameters
|
|
|
|
|
# @return Custom parameters
|
|
|
|
|
sub getCustomTemplateParameters {
|
|
|
|
|
|
|
|
|
|
my $self = shift;
|
|
|
|
|
my $customTplParams = {};
|
|
|
|
|
|
|
|
|
|
foreach ( keys %$self ) {
|
|
|
|
|
next unless ( $_ =~ /^tpl_(.+)$/ );
|
|
|
|
|
my $tplParam = $1;
|
|
|
|
|
my $tplValue = $self->{ "tpl_" . $tplParam };
|
|
|
|
|
$self->lmLog( "Set custom template parameter $tplParam with $tplValue",
|
|
|
|
|
'debug' );
|
|
|
|
|
|
|
|
|
|
$customTplParams->{$tplParam} = $tplValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $customTplParams;
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
__END__
|
|
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
2010-01-03 09:09:59 +01:00
|
|
|
|
=encoding utf8
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
Lemonldap::NG::Portal::Simple - Base module for building Lemonldap::NG compatible portals
|
|
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
|
|
use Lemonldap::NG::Portal::Simple;
|
|
|
|
|
my $portal = new Lemonldap::NG::Portal::Simple(
|
2007-04-10 07:15:26 +02:00
|
|
|
|
domain => 'example.com',
|
2006-12-18 12:32:33 +01:00
|
|
|
|
globalStorage => 'Apache::Session::MySQL',
|
2007-01-14 20:39:07 +01:00
|
|
|
|
globalStorageOptions => {
|
|
|
|
|
DataSource => 'dbi:mysql:database=dbname;host=127.0.0.1',
|
|
|
|
|
UserName => 'db_user',
|
|
|
|
|
Password => 'db_password',
|
|
|
|
|
TableName => 'sessions',
|
|
|
|
|
LockDataSource => 'dbi:mysql:database=dbname;host=127.0.0.1',
|
|
|
|
|
LockUserName => 'db_user',
|
|
|
|
|
LockPassword => 'db_password',
|
|
|
|
|
},
|
2007-05-15 06:31:10 +02:00
|
|
|
|
ldapServer => 'ldap.domaine.com,ldap-backup.domaine.com',
|
2007-01-14 20:39:07 +01:00
|
|
|
|
securedCookie => 1,
|
2008-09-10 12:40:01 +02:00
|
|
|
|
exportedVars => {
|
|
|
|
|
uid => 'uid',
|
|
|
|
|
cn => 'cn',
|
|
|
|
|
mail => 'mail',
|
|
|
|
|
appli => 'appli',
|
2008-12-07 21:07:52 +01:00
|
|
|
|
},
|
|
|
|
|
# Activate SOAP service
|
|
|
|
|
Soap => 1
|
2006-12-18 12:32:33 +01:00
|
|
|
|
);
|
2008-12-07 21:07:52 +01:00
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
if($portal->process()) {
|
|
|
|
|
# Write here the menu with CGI methods. This page is displayed ONLY IF
|
|
|
|
|
# the user was not redirected here.
|
2013-10-17 21:21:45 +02:00
|
|
|
|
print $portal->header('text/html; charset=utf-8'); # DON'T FORGET THIS (see L<CGI(3)>)
|
2006-12-18 12:32:33 +01:00
|
|
|
|
print "...";
|
|
|
|
|
|
|
|
|
|
# or redirect the user to the menu
|
|
|
|
|
print $portal->redirect( -uri => 'https://portal/menu');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
# Write here the html form used to authenticate with CGI methods.
|
|
|
|
|
# $portal->error returns the error message if athentification failed
|
|
|
|
|
# Warning: by defaut, input names are "user" and "password"
|
2013-10-17 21:21:45 +02:00
|
|
|
|
print $portal->header('text/html; charset=utf-8'); # DON'T FORGET THIS (see L<CGI(3)>)
|
2006-12-18 12:32:33 +01:00
|
|
|
|
print "...";
|
|
|
|
|
print '<form method="POST">';
|
|
|
|
|
# In your form, the following value is required for redirection
|
|
|
|
|
print '<input type="hidden" name="url" value="'.$portal->param('url').'">';
|
|
|
|
|
# Next, login and password
|
|
|
|
|
print 'Login : <input name="user"><br>';
|
2015-06-11 14:59:20 +02:00
|
|
|
|
print 'Password : <input name="password" type="password">';
|
2006-12-18 12:32:33 +01:00
|
|
|
|
print '<input type="submit" value="go" />';
|
|
|
|
|
print '</form>';
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-07 21:07:52 +01:00
|
|
|
|
SOAP mode authentication (client) :
|
|
|
|
|
|
|
|
|
|
#!/usr/bin/perl -l
|
|
|
|
|
|
|
|
|
|
use SOAP::Lite;
|
|
|
|
|
use Data::Dumper;
|
|
|
|
|
|
|
|
|
|
my $soap =
|
|
|
|
|
SOAP::Lite->proxy('http://auth.example.com/')
|
2009-02-08 20:12:08 +01:00
|
|
|
|
->uri('urn:/Lemonldap::NG::Common::CGI::SOAPService');
|
2008-12-07 21:07:52 +01:00
|
|
|
|
my $r = $soap->getCookies( 'user', 'password' );
|
|
|
|
|
|
|
|
|
|
# Catch SOAP errors
|
|
|
|
|
if ( $r->fault ) {
|
|
|
|
|
print STDERR "SOAP Error: " . $r->fault->{faultstring};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
my $res = $r->result();
|
|
|
|
|
|
|
|
|
|
# If authentication failed, display error
|
|
|
|
|
if ( $res->{error} ) {
|
2012-02-15 12:58:32 +01:00
|
|
|
|
print STDERR "Error: " . $soap->error( $res->{error} )->result();
|
2008-12-07 21:07:52 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# print session-ID
|
|
|
|
|
else {
|
|
|
|
|
print "Cookie: lemonldap=" . $res->{cookies}->{lemonldap};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
|
|
Lemonldap::NG::Portal::Simple is the base module for building Lemonldap::NG
|
|
|
|
|
compatible portals. You can use it either by inheritance or by writing
|
|
|
|
|
anonymous methods like in the example above.
|
|
|
|
|
|
2006-12-24 09:37:27 +01:00
|
|
|
|
See L<Lemonldap::NG::Portal::SharedConf> for a complete example of use of
|
2006-12-18 12:32:33 +01:00
|
|
|
|
Lemonldap::Portal::* libraries.
|
|
|
|
|
|
|
|
|
|
=head1 METHODS
|
|
|
|
|
|
|
|
|
|
=head2 Constructor (new)
|
|
|
|
|
|
|
|
|
|
=head3 Args
|
|
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
|
2010-06-08 12:39:34 +02:00
|
|
|
|
=item * ldapServer: server(s) used to retrive session information and to valid
|
2007-05-15 06:31:10 +02:00
|
|
|
|
credentials (localhost by default). More than one server can be set here
|
|
|
|
|
separated by commas. The servers will be tested in the specifies order.
|
2007-07-22 22:30:27 +02:00
|
|
|
|
To use TLS, set "ldap+tls://server" and to use LDAPS, set "ldaps://server"
|
|
|
|
|
instead of server name. If you use TLS, you can set any of the
|
|
|
|
|
Net::LDAP->start_tls() sub like this:
|
|
|
|
|
"ldap/tls://server/verify=none&capath=/etc/ssl"
|
|
|
|
|
You can also use caFile and caPath parameters.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=item * ldapPort: tcp port used by ldap server.
|
|
|
|
|
|
|
|
|
|
=item * ldapBase: base of the ldap directory.
|
|
|
|
|
|
|
|
|
|
=item * managerDn: dn to used to connect to ldap server. By default, anonymous
|
|
|
|
|
bind is used.
|
|
|
|
|
|
|
|
|
|
=item * managerPassword: password to used to connect to ldap server. By
|
|
|
|
|
default, anonymous bind is used.
|
|
|
|
|
|
2007-07-22 22:30:27 +02:00
|
|
|
|
=item * securedCookie: set it to 1 if you want to protect user cookies.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2007-07-22 22:30:27 +02:00
|
|
|
|
=item * cookieName: name of the cookie used by Lemonldap::NG (lemon by default).
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=item * domain: cookie domain. You may have to give it else the SSO will work
|
|
|
|
|
only on your server.
|
|
|
|
|
|
|
|
|
|
=item * globalStorage: required: L<Apache::Session> library to used to store
|
2010-06-08 12:39:34 +02:00
|
|
|
|
session information.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=item * globalStorageOptions: parameters to bind to L<Apache::Session> module
|
|
|
|
|
|
|
|
|
|
=item * authentication: sheme to authenticate users (default: "ldap"). It can
|
|
|
|
|
be set to:
|
|
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
|
|
|
|
|
=item * B<SSL>: See L<Lemonldap::NG::Portal::AuthSSL>.
|
|
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
2007-07-22 22:30:27 +02:00
|
|
|
|
=item * caPath, caFile: if you use ldap+tls you can overwrite cafile or capath
|
2010-01-03 09:09:59 +01:00
|
|
|
|
options with those parameters. This is useful if you use a shared
|
2007-07-22 22:30:27 +02:00
|
|
|
|
configuration.
|
|
|
|
|
|
2008-05-10 11:31:43 +02:00
|
|
|
|
=item * ldapPpolicyControl: set it to 1 if you want to use LDAP Password Policy
|
|
|
|
|
|
2010-01-11 15:02:43 +01:00
|
|
|
|
=item * grantSessionRule: rule applied to grant session opening for a user. Can
|
|
|
|
|
use all exported attributes, macros, groups and custom functions.
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=back
|
|
|
|
|
|
|
|
|
|
=head2 Methods that can be overloaded
|
|
|
|
|
|
2007-05-05 16:13:44 +02:00
|
|
|
|
All the functions above can be overloaded to adapt Lemonldap::NG to your
|
2006-12-18 12:32:33 +01:00
|
|
|
|
environment. They MUST return one of the exported constants (see above)
|
|
|
|
|
and are called in this order by process().
|
|
|
|
|
|
|
|
|
|
=head3 controlUrlOrigin
|
|
|
|
|
|
2007-05-05 16:13:44 +02:00
|
|
|
|
If the user was redirected by a Lemonldap::NG handler, stores the url that will be
|
2006-12-18 12:32:33 +01:00
|
|
|
|
used to redirect the user after authentication.
|
|
|
|
|
|
|
|
|
|
=head3 controlExistingSession
|
|
|
|
|
|
2007-02-11 09:31:56 +01:00
|
|
|
|
Controls if a previous session is always available. If true, it call the sub
|
|
|
|
|
C<existingSession> with two parameters: id and a scalar tied on Apache::Session
|
2015-09-22 07:38:23 +02:00
|
|
|
|
module choosed to store sessions. See below
|
2007-02-11 09:31:56 +01:00
|
|
|
|
|
|
|
|
|
=head3 existingSession
|
|
|
|
|
|
|
|
|
|
This sub is called only if a previous session exists and is available. By
|
|
|
|
|
defaults, it returns PE_OK so user is re-authenticated. You can overload it:
|
|
|
|
|
for example if existingSession just returns PE_DONE: authenticated users are
|
|
|
|
|
not re-authenticated and C<>process> returns true.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=head3 extractFormInfo
|
|
|
|
|
|
2008-06-11 08:00:26 +02:00
|
|
|
|
Method implemented into Lemonldap::NG::Portal::Auth* modules. By default
|
|
|
|
|
(ldap bind), converts form input into object variables ($self->{user} and
|
2006-12-18 12:32:33 +01:00
|
|
|
|
$self->{password}).
|
|
|
|
|
|
|
|
|
|
=head3 formateParams
|
|
|
|
|
|
|
|
|
|
Does nothing. To be overloaded if needed.
|
|
|
|
|
|
|
|
|
|
=head3 formateFilter
|
|
|
|
|
|
|
|
|
|
Creates the ldap filter using $self->{user}. By default :
|
|
|
|
|
|
2008-05-30 06:47:32 +02:00
|
|
|
|
$self->{filter} = "(&(uid=" . $self->{user} . ")(objectClass=inetOrgPerson))";
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2009-04-05 10:12:16 +02:00
|
|
|
|
If $self->{AuthLDAPFilter} is set, it is used instead of this. This is used by
|
2008-06-11 08:00:26 +02:00
|
|
|
|
Lemonldap::NG::Portal::Auth* modules to overload filter.
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head3 connectLDAP
|
|
|
|
|
|
|
|
|
|
Connects to LDAP server.
|
|
|
|
|
|
|
|
|
|
=head3 bind
|
|
|
|
|
|
|
|
|
|
Binds to the LDAP server using $self->{managerDn} and $self->{managerPassword}
|
|
|
|
|
if exist. Anonymous bind is provided else.
|
|
|
|
|
|
|
|
|
|
=head3 search
|
|
|
|
|
|
|
|
|
|
Retrives the LDAP entry corresponding to the user using $self->{filter}.
|
|
|
|
|
|
2008-06-11 08:00:26 +02:00
|
|
|
|
=head3 setAuthSessionInfo
|
|
|
|
|
|
|
|
|
|
Same as setSessionInfo but implemented in Lemonldap::NG::Portal::Auth* modules.
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head3 setSessionInfo
|
|
|
|
|
|
|
|
|
|
Prepares variables to store in central cache (stored temporarily in
|
|
|
|
|
C<$self->{sessionInfo}>). It use C<exportedVars> entry (passed to the new sub)
|
|
|
|
|
if defined to know what to store else it stores uid, cn and mail attributes.
|
|
|
|
|
|
2008-09-19 17:28:00 +02:00
|
|
|
|
=head3 getSessionInfo
|
|
|
|
|
|
|
|
|
|
Pick up an information stored in session.
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head3 setGroups
|
|
|
|
|
|
|
|
|
|
Does nothing by default.
|
|
|
|
|
|
|
|
|
|
=head3 authenticate
|
|
|
|
|
|
2008-06-11 08:00:26 +02:00
|
|
|
|
Method implemented in Lemonldap::NG::Portal::Auth* modules. By default (ldap),
|
|
|
|
|
authenticates the user by rebinding to the LDAP server using the dn retrived
|
2006-12-18 12:32:33 +01:00
|
|
|
|
with search() and the password.
|
|
|
|
|
|
2010-01-11 15:02:43 +01:00
|
|
|
|
=head3 grantSession
|
|
|
|
|
|
|
|
|
|
Use grantSessionRule parameter to allow session opening.
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head3 store
|
|
|
|
|
|
2010-06-08 12:39:34 +02:00
|
|
|
|
Stores information collected by setSessionInfo into the central cache.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
The portal connects the cache using the L<Apache::Session> module passed by
|
|
|
|
|
the globalStorage parameters (see constructor).
|
|
|
|
|
|
|
|
|
|
=head3 unbind
|
|
|
|
|
|
|
|
|
|
Disconnects from the LDAP server.
|
|
|
|
|
|
|
|
|
|
=head3 buildCookie
|
|
|
|
|
|
2007-05-05 16:13:44 +02:00
|
|
|
|
Creates the Lemonldap::NG cookie.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=head3 log
|
|
|
|
|
|
|
|
|
|
Does nothing. To be overloaded if wanted.
|
|
|
|
|
|
2007-01-11 07:42:57 +01:00
|
|
|
|
=head3 autoRedirect
|
|
|
|
|
|
|
|
|
|
Redirects the user to the url stored by controlUrlOrigin().
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head2 Other methods
|
|
|
|
|
|
|
|
|
|
=head3 process
|
|
|
|
|
|
|
|
|
|
Main method.
|
|
|
|
|
|
|
|
|
|
=head3 error
|
|
|
|
|
|
|
|
|
|
Returns the error message corresponding to the error returned by the methods
|
|
|
|
|
described above
|
|
|
|
|
|
2008-09-19 17:28:00 +02:00
|
|
|
|
=head3 error_type
|
|
|
|
|
|
|
|
|
|
Give the type of the error (positive, warning or positive)
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head3 _bind( $ldap, $dn, $password )
|
|
|
|
|
|
2008-06-06 05:51:39 +02:00
|
|
|
|
Method used to bind to the ldap server.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=head3 header
|
|
|
|
|
|
2007-05-05 16:13:44 +02:00
|
|
|
|
Overloads the CGI::header method to add Lemonldap::NG cookie.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=head3 redirect
|
|
|
|
|
|
2007-05-05 16:13:44 +02:00
|
|
|
|
Overloads the CGI::redirect method to add Lemonldap::NG cookie.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=head2 EXPORT
|
|
|
|
|
|
|
|
|
|
=head3 Constants
|
|
|
|
|
|
|
|
|
|
=over 5
|
|
|
|
|
|
|
|
|
|
=item * B<PE_OK>: all is good
|
|
|
|
|
|
|
|
|
|
=item * B<PE_SESSIONEXPIRED>: the user session has expired
|
|
|
|
|
|
|
|
|
|
=item * B<PE_FORMEMPTY>: Nothing was entered in the login form
|
|
|
|
|
|
|
|
|
|
=item * B<PE_USERNOTFOUND>: the user was not found in the (ldap) directory
|
|
|
|
|
|
|
|
|
|
=item * B<PE_WRONGMANAGERACCOUNT>: the account used to bind to LDAP server in order to
|
|
|
|
|
find the user distinguished name (dn) was refused by the server
|
|
|
|
|
|
|
|
|
|
=item * B<PE_BADCREDENTIALS>: bad login or password
|
|
|
|
|
|
|
|
|
|
=item * B<PE_LDAPERROR>: abnormal error from ldap
|
|
|
|
|
|
|
|
|
|
=item * B<PE_APACHESESSIONERROR>: abnormal error from Apache::Session
|
|
|
|
|
|
|
|
|
|
=item * B<PE_FIRSTACCESS>: First access to the portal
|
|
|
|
|
|
|
|
|
|
=item * B<PE_BADCERTIFICATE>: Wrong certificate
|
|
|
|
|
|
2008-06-11 08:00:26 +02:00
|
|
|
|
=item * PE_PP_ACCOUNT_LOCKED: account locked
|
|
|
|
|
|
|
|
|
|
=item * PE_PP_PASSWORD_EXPIRED: password axpired
|
|
|
|
|
|
|
|
|
|
=item * PE_CERTIFICATEREQUIRED: certificate required
|
|
|
|
|
|
|
|
|
|
=item * PE_ERROR: unclassified error
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=back
|
|
|
|
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
|
|
2007-04-02 21:13:05 +02:00
|
|
|
|
L<Lemonldap::NG::Handler>, L<Lemonldap::NG::Portal::SharedConf>, L<CGI>,
|
2010-10-26 08:08:16 +02:00
|
|
|
|
L<http://lemonldap-ng.org/>
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
2013-01-31 06:33:10 +01:00
|
|
|
|
=over
|
|
|
|
|
|
|
|
|
|
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
|
|
|
|
|
|
2013-10-19 18:34:20 +02:00
|
|
|
|
=item François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
|
2013-01-31 06:33:10 +01:00
|
|
|
|
|
|
|
|
|
=item Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
|
|
|
|
|
|
|
|
|
=item Sandro Cazzaniga, E<lt>cazzaniga.sandro@gmail.comE<gt>
|
|
|
|
|
|
2013-02-01 06:37:38 +01:00
|
|
|
|
=item Thomas Chemineau, E<lt>thomas.chemineau@gmail.comE<gt>
|
2013-01-31 06:33:10 +01:00
|
|
|
|
|
|
|
|
|
=back
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
2007-04-14 15:12:11 +02:00
|
|
|
|
=head1 BUG REPORT
|
|
|
|
|
|
|
|
|
|
Use OW2 system to report bug or ask for features:
|
2010-10-26 08:08:16 +02:00
|
|
|
|
L<http://jira.ow2.org>
|
2007-04-14 15:12:11 +02:00
|
|
|
|
|
|
|
|
|
=head1 DOWNLOAD
|
|
|
|
|
|
|
|
|
|
Lemonldap::NG is available at
|
|
|
|
|
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
|
|
|
|
|
|
2006-12-18 12:32:33 +01:00
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
|
|
2013-01-31 06:33:10 +01:00
|
|
|
|
=over
|
|
|
|
|
|
2015-06-18 13:00:24 +02:00
|
|
|
|
=item Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 by Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
2013-01-31 06:33:10 +01:00
|
|
|
|
|
|
|
|
|
=item Copyright (C) 2012 by Sandro Cazzaniga, E<lt>cazzaniga.sandro@gmail.comE<gt>
|
|
|
|
|
|
2013-10-19 18:34:20 +02:00
|
|
|
|
=item Copyright (C) 2012, 2012, 2013 by François-Xavier Deltombe, E<lt>fxdeltombe@gmail.com.E<gt>
|
2013-01-31 06:33:10 +01:00
|
|
|
|
|
|
|
|
|
=item Copyright (C) 2006, 2008, 2009, 2010, 2011, 2012, 2012, 2013 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
|
|
|
|
|
|
2013-02-01 06:37:38 +01:00
|
|
|
|
=item Copyright (C) 2010, 2011 by Thomas Chemineau, E<lt>thomas.chemineau@gmail.comE<gt>
|
2013-01-31 06:33:10 +01:00
|
|
|
|
|
|
|
|
|
=back
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
2013-01-31 06:33:10 +01:00
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2, 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, see L<http://www.gnu.org/licenses/>.
|
2006-12-18 12:32:33 +01:00
|
|
|
|
|
|
|
|
|
=cut
|