Commit 80f5d06e authored by dcoutadeur dcoutadeur's avatar dcoutadeur dcoutadeur
Browse files

perl tidy

parent 6533b0a3
......@@ -212,7 +212,9 @@ sub getConf {
# Create cipher object
unless ( $args->{raw} ) {
eval { $res->{cipher} = Lemonldap::NG::Common::Crypto->new( $res->{key} ); };
eval {
$res->{cipher} = Lemonldap::NG::Common::Crypto->new( $res->{key} );
};
if ($@) {
$msg .= "Bad key: $@. \n";
}
......
......@@ -50,7 +50,8 @@ sub defaultValues {
'globalStorage' => 'Apache::Session::File',
'globalStorageOptions' => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'generateModule' => 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
},
'groups' => {},
......@@ -173,24 +174,33 @@ sub defaultValues {
'registerTimeout' => 0,
'remoteGlobalStorage' => 'Lemonldap::NG::Common::Apache::Session::SOAP',
'remoteGlobalStorageOptions' => {
'ns' => 'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
'ns' =>
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
'proxy' => 'http://auth.example.com/sessions'
},
'requireToken' => 1,
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
'samlAuthnContextMapKerberos' => 4,
'samlAuthnContextMapPassword' => 2,
'samlAuthnContextMapPasswordProtectedTransport' => 3,
'samlAuthnContextMapTLSClient' => 5,
'samlEntityID' => '#PORTAL#/saml/metadata',
'samlIdPResolveCookie' => 'lemonldapidp',
'samlIDPSSODescriptorArtifactResolutionServiceArtifact' => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact',
'samlIDPSSODescriptorSingleLogoutServiceHTTPPost' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn',
'samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn',
'samlIDPSSODescriptorSingleLogoutServiceSOAP' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/singleLogoutSOAP;',
'samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/singleSignOnArtifact;',
'samlIDPSSODescriptorSingleSignOnServiceHTTPPost' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleSignOn;',
'samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleSignOn;',
'samlIDPSSODescriptorArtifactResolutionServiceArtifact' =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact',
'samlIDPSSODescriptorSingleLogoutServiceHTTPPost' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn',
'samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleLogout;#PORTAL#/saml/singleLogoutReturn',
'samlIDPSSODescriptorSingleLogoutServiceSOAP' =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/singleLogoutSOAP;',
'samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/singleSignOnArtifact;',
'samlIDPSSODescriptorSingleSignOnServiceHTTPPost' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/singleSignOn;',
'samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/singleSignOn;',
'samlIDPSSODescriptorWantAuthnRequestsSigned' => 1,
'samlMetadataForceUTF8' => 1,
'samlNameIDFormatMapEmail' => 'mail',
......@@ -201,13 +211,19 @@ sub defaultValues {
'samlOrganizationName' => 'Example',
'samlOrganizationURL' => 'http://www.example.com',
'samlRelayStateTimeout' => 600,
'samlSPSSODescriptorArtifactResolutionServiceArtifact' => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact',
'samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact' => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact',
'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' => '0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost',
'samlSPSSODescriptorArtifactResolutionServiceArtifact' =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/artifact',
'samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact' =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact',
'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' =>
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost',
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
'samlSPSSODescriptorSingleLogoutServiceHTTPPost' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
'samlSPSSODescriptorSingleLogoutServiceSOAP' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/proxySingleLogoutSOAP;',
'samlSPSSODescriptorSingleLogoutServiceHTTPPost' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
'samlSPSSODescriptorSingleLogoutServiceSOAP' =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/proxySingleLogoutSOAP;',
'samlSPSSODescriptorWantAssertionsSigned' => 1,
'securedCookie' => 0,
'slaveAuthnLevel' => 2,
......
......@@ -475,7 +475,7 @@ sub _casMetaDataNodes {
# Return all exported attributes if asked
if ( $query =~
/^(?:cas${type}MetaDataExportedVars|casSrvMetaDataOptionsProxiedServices)$/
/^(?:cas${type}MetaDataExportedVars|casSrvMetaDataOptionsProxiedServices)$/
)
{
my $pk = eval { $self->getConfKey( $req, $query )->{$partner} } // {};
......
......@@ -105,7 +105,8 @@ sub unset_header_in {
my $h = shift;
my $h2 = lc $h;
$h2 =~ s/-/_/g;
$request->env->{'psgi.r'}->headers_in->unset($h) if ( $h1 eq $h2 );
$request->env->{'psgi.r'}->headers_in->unset($h)
if ( $h1 eq $h2 );
return 1;
}
);
......
......@@ -104,10 +104,12 @@ sub init {
}
$self->menuLinks( [] );
if ( my $portal =
if (
my $portal =
$conf->{cfgNum}
? Lemonldap::NG::Handler::PSGI::Main->tsv->{portal}->()
: $conf->{portal} )
: $conf->{portal}
)
{
push @{ $self->menuLinks },
{
......
......@@ -372,7 +372,8 @@ sub attributes {
portalErrorOnMailNotFound => {
type => 'bool',
default => 0,
documentation => 'Show error if mail is not found in password reset process',
documentation =>
'Show error if mail is not found in password reset process',
},
portalOpenLinkInNewWindow => {
type => 'bool',
......
......@@ -172,7 +172,8 @@ sub tree {
title => 'dbiPassword',
help => 'authdbi.html#password',
form => 'simpleInputContainer',
nodes => ['dbiAuthPasswordHash',
nodes => [
'dbiAuthPasswordHash',
{
title => 'dbiDynamicHash',
help => 'authdbi.html#password',
......@@ -180,8 +181,8 @@ sub tree {
nodes => [
'dbiDynamicHashEnabled',
'dbiDynamicHashValidSchemes',
'dbiDynamicHashValidSaltedSchemes',
'dbiDynamicHashNewPasswordScheme'
'dbiDynamicHashValidSaltedSchemes',
'dbiDynamicHashNewPasswordScheme'
]
}
]
......
......@@ -473,10 +473,13 @@ sub _scanNodes {
}
}
elsif ( $target =~
/^(?:$casSrvMetaDataNodeKeys|$casAppMetaDataNodeKeys)/o )
/^(?:$casSrvMetaDataNodeKeys|$casAppMetaDataNodeKeys)/o
)
{
$self->set( $optKey, [ $oldName, $key ],
$target, $leaf->{data} );
$self->set(
$optKey, [ $oldName, $key ],
$target, $leaf->{data}
);
}
else {
push @{ $self->errors },
......
......@@ -315,8 +315,8 @@ sub tests {
my %entityIds;
foreach my $spId ( keys %{ $conf->{samlSPMetaDataXML} } ) {
unless (
$conf->{samlSPMetaDataXML}->{$spId}->{samlSPMetaDataXML}
=~ /entityID=(['"])(.+?)\1/si )
$conf->{samlSPMetaDataXML}->{$spId}->{samlSPMetaDataXML} =~
/entityID=(['"])(.+?)\1/si )
{
push @msg, "$spId SAML metadata has no EntityID";
$res = 0;
......
......@@ -78,7 +78,8 @@ sub extractFormInfo {
# another backend (Combination)
# switch to another backend
elsif ( defined $req->param('kerberos') ) {
$self->userLogger->warn('Kerberos authentication has failed, back to portal');
$self->userLogger->warn(
'Kerberos authentication has failed, back to portal');
return PE_BADCREDENTIALS;
}
......@@ -110,16 +111,11 @@ sub extractFormInfo {
$ENV{KRB5_KTNAME} = $self->keytab;
my $gss_client_name;
my $status = GSSAPI::Context::accept(
my $server_context,
GSS_C_NO_CREDENTIAL,
$data,
GSS_C_NO_CHANNEL_BINDINGS,
$gss_client_name,
undef,
my $gss_output_token,
my $out_flags,
my $out_time,
my $gss_delegated_cred
my $server_context, GSS_C_NO_CREDENTIAL,
$data, GSS_C_NO_CHANNEL_BINDINGS,
$gss_client_name, undef,
my $gss_output_token, my $out_flags,
my $out_time, my $gss_delegated_cred
);
unless ($status) {
$self->logger->error('Unable to accept security context');
......
......@@ -331,7 +331,7 @@ sub validateST {
my $proxy_url;
if (%$proxied) {
$proxy_url = $self->p->fullUrl($req);
die if($proxy_url =~ /casProxy=1/);
die if ( $proxy_url =~ /casProxy=1/ );
$proxy_url .= ( $proxy_url =~ /\?/ ? '&' : '?' ) . 'casProxy=1';
if ( $self->conf->{authChoiceParam}
and my $tmp = $req->param( $self->conf->{authChoiceParam} ) )
......
......@@ -98,10 +98,9 @@ sub get_password {
my @rows = ();
eval {
my $sth = $dbh->prepare(
"SELECT $passwordCol FROM $table WHERE $loginCol=?"
);
$sth->execute( $user);
my $sth =
$dbh->prepare( "SELECT $passwordCol FROM $table WHERE $loginCol=?" );
$sth->execute($user);
@rows = $sth->fetchrow_array();
};
if ($@) {
......@@ -110,11 +109,11 @@ sub get_password {
}
if ( @rows == 1 ) {
$self->logger->debug( "Successfully got password from database" );
$self->logger->debug("Successfully got password from database");
return $rows[0];
}
else {
$self->userLogger->warn( "Unable to check password for $user" );
$self->userLogger->warn("Unable to check password for $user");
return "";
}
}
......@@ -128,6 +127,7 @@ sub get_password {
# @param password the password to hash
# @return hashed password
sub hash_password_from_database {
# Remark: database function must get hexadecimal input
# and send back hexadecimal output
my $self = shift;
......@@ -146,13 +146,17 @@ sub hash_password_from_database {
@rows = $sth->fetchrow_array();
};
if ($@) {
$self->lmLog( "DBI error while hashing with '$dbmethod' hash function: $@", 'error' );
$self->userLogger->warn( "Unable to check password" );
$self->lmLog(
"DBI error while hashing with '$dbmethod' hash function: $@",
'error' );
$self->userLogger->warn("Unable to check password");
return "";
}
if ( @rows == 1 ) {
$self->logger->debug( "Successfully hashed password with $dbmethod hash function in database" );
$self->logger->debug(
"Successfully hashed password with $dbmethod hash function in database"
);
# convert salt to binary
my $dbsaltb = pack 'H*', $dbsalt;
......@@ -160,14 +164,14 @@ sub hash_password_from_database {
# convert result to binary
my $res = pack 'H*', $rows[0];
return encode_base64($res . $dbsaltb ,'');
return encode_base64( $res . $dbsaltb, '' );
}
else {
$self->userLogger->warn( "Unable to check password with '$dbmethod'" );
$self->userLogger->warn("Unable to check password with '$dbmethod'");
return "";
}
# Return encode_base64(SQL_METHOD(password + salt) + salt)
# Return encode_base64(SQL_METHOD(password + salt) + salt)
}
## @method protected Lemonldap::NG::Portal::_DBI get_salt(string dbhash)
......@@ -200,9 +204,9 @@ sub get_salt {
sub gen_salt {
my $self = shift;
my $dbsalt;
my @set = ('0' ..'9', 'A' .. 'F');
my @set = ( '0' .. '9', 'A' .. 'F' );
$dbsalt = join '' => map $set[rand @set], 1 .. 16;
$dbsalt = join '' => map $set[ rand @set ], 1 .. 16;
return $dbsalt;
}
......@@ -225,9 +229,11 @@ sub dynamic_hash_password {
my $table = shift;
my $loginCol = shift;
my $passwordCol = shift;
# Authorized hash schemes and salted hash schemes
my @validSchemes = split / /, $self->conf->{dbiDynamicHashValidSchemes};
my @validSaltedSchemes = split / /, $self->conf->{dbiDynamicHashValidSaltedSchemes};
my @validSaltedSchemes = split / /,
$self->conf->{dbiDynamicHashValidSaltedSchemes};
my $dbhash; # hash currently stored in database
my $dbscheme; # current hash scheme stored in database
......@@ -236,8 +242,9 @@ sub dynamic_hash_password {
my $hash; # hash to compute from user password
# Search hash from database
$self->logger->debug( "Hash scheme is to be found in database" );
$dbhash = $self->get_password($dbh, $user, $table, $loginCol, $passwordCol);
$self->logger->debug("Hash scheme is to be found in database");
$dbhash =
$self->get_password( $dbh, $user, $table, $loginCol, $passwordCol );
# Get the scheme
$dbscheme = $dbhash;
......@@ -245,14 +252,16 @@ sub dynamic_hash_password {
$dbscheme = "" if $dbscheme eq $dbhash;
# no hash scheme => assume clear text
if($dbscheme eq "") {
$self->logger->info( "Password has no hash scheme" );
if ( $dbscheme eq "" ) {
$self->logger->info("Password has no hash scheme");
return "?";
}
# salted hash scheme
elsif(grep( /^$dbscheme$/, @validSaltedSchemes )) {
$self->logger->info( "Valid salted hash scheme: $dbscheme found for user $user" );
elsif ( grep( /^$dbscheme$/, @validSaltedSchemes ) ) {
$self->logger->info(
"Valid salted hash scheme: $dbscheme found for user $user");
# extract non salted hash scheme
$dbmethod = $dbscheme;
......@@ -260,29 +269,36 @@ sub dynamic_hash_password {
# extract the salt
$dbsalt = $self->get_salt($dbhash);
$self->logger->debug( "Get salt from password: $dbsalt");
$self->logger->debug("Get salt from password: $dbsalt");
# Hash password with given hash scheme and salt
$hash = $self->hash_password_from_database($dbh, $dbmethod, $dbsalt, $password);
$hash =
$self->hash_password_from_database( $dbh, $dbmethod, $dbsalt,
$password );
$hash = "{$dbscheme}$hash";
return "'$hash'";
}
# static hash scheme
elsif(grep( /^$dbscheme$/, @validSchemes )) {
$self->logger->info( "Valid hash scheme: $dbscheme found for user $user" );
elsif ( grep( /^$dbscheme$/, @validSchemes ) ) {
$self->logger->info(
"Valid hash scheme: $dbscheme found for user $user");
# Hash given password with given hash scheme and no salt
$hash = $self->hash_password_from_database($dbh, $dbscheme, "", $password);
$hash =
$self->hash_password_from_database( $dbh, $dbscheme, "", $password );
$hash = "{$dbscheme}$hash";
return "'$hash'";
}
# no valid hash scheme
else {
$self->lmLog( "No valid hash scheme: $dbscheme for user $user", 'error' );
$self->userLogger->warn( "Unable to check password for $user" );
$self->lmLog( "No valid hash scheme: $dbscheme for user $user",
'error' );
$self->userLogger->warn("Unable to check password for $user");
return "";
}
......@@ -302,23 +318,27 @@ sub dynamic_hash_new_password {
my $user = shift;
my $password = shift;
my $dbscheme = $self->conf->{dbiDynamicHashNewPasswordScheme} || "";
# Authorized hash schemes and salted hash schemes
my @validSchemes = split / /, $self->conf->{dbiDynamicHashValidSchemes};
my @validSaltedSchemes = split / /, $self->conf->{dbiDynamicHashValidSaltedSchemes};
my @validSaltedSchemes = split / /,
$self->conf->{dbiDynamicHashValidSaltedSchemes};
my $dbmethod; # static hash method corresponding to a database function
my $dbsalt; # salt to generate for new hashed password
my $hash; # hash to compute from user password
# no hash scheme => assume clear text
if($dbscheme eq "") {
$self->logger->info( "No hash scheme selected, storing password in clear text" );
if ( $dbscheme eq "" ) {
$self->logger->info(
"No hash scheme selected, storing password in clear text");
return "?";
}
# salted hash scheme
elsif(grep( /^$dbscheme$/, @validSaltedSchemes )) {
$self->logger->info( "Selected salted hash scheme: $dbscheme" );
elsif ( grep( /^$dbscheme$/, @validSaltedSchemes ) ) {
$self->logger->info("Selected salted hash scheme: $dbscheme");
# extract non salted hash scheme
$dbmethod = $dbscheme;
......@@ -326,29 +346,35 @@ sub dynamic_hash_new_password {
# generate the salt
$dbsalt = $self->gen_salt();
$self->logger->debug( "Generated salt: $dbsalt" );
$self->logger->debug("Generated salt: $dbsalt");
# Hash given password with given hash scheme and salt
$hash = $self->hash_password_from_database($dbh, $dbmethod, $dbsalt, $password);
$hash =
$self->hash_password_from_database( $dbh, $dbmethod, $dbsalt,
$password );
$hash = "{$dbscheme}$hash";
return "'$hash'";
}
# static hash scheme
elsif(grep( /^$dbscheme$/, @validSchemes )) {
$self->logger->info( "Selected hash scheme: $dbscheme" );
elsif ( grep( /^$dbscheme$/, @validSchemes ) ) {
$self->logger->info("Selected hash scheme: $dbscheme");
# Hash given password with given hash scheme and no salt
$hash = $self->hash_password_from_database($dbh, $dbscheme, "", $password);
$hash =
$self->hash_password_from_database( $dbh, $dbscheme, "", $password );
$hash = "{$dbscheme}$hash";
return "'$hash'";
}
# no valid hash scheme
else {
$self->lmLog( "No selected hash scheme: $dbscheme is invalid", 'error' );
$self->userLogger->warn( "Unable to store password for $user" );
$self->lmLog( "No selected hash scheme: $dbscheme is invalid",
'error' );
$self->userLogger->warn("Unable to store password for $user");
return "";
}
......@@ -374,15 +400,17 @@ sub check_password {
my $passwordsql;
if ( $dynamicHash == 1 ) {
# Dynamic password hashes
$passwordsql =
$self->dynamic_hash_password( $self->dbh, $user, $password, $table, $loginCol, $passwordCol );
$self->dynamic_hash_password( $self->dbh, $user, $password, $table,
$loginCol, $passwordCol );
}
else
{
else {
# Static Password hashes
$passwordsql =
$self->hash_password_for_select( "?", $self->conf->{dbiAuthPasswordHash} );
$self->hash_password_for_select( "?",
$self->conf->{dbiAuthPasswordHash} );
}
my @rows = ();
......@@ -391,7 +419,7 @@ sub check_password {
"SELECT $loginCol FROM $table WHERE $loginCol=? AND $passwordCol=$passwordsql"
);
$sth->execute( $user, $password ) if $passwordsql =~ /.*\?.*/;
$sth->execute( $user ) unless $passwordsql =~ /.*\?.*/;
$sth->execute($user) unless $passwordsql =~ /.*\?.*/;
@rows = $sth->fetchrow_array();
};
if ($@) {
......
......@@ -29,14 +29,16 @@ sub modifyPassword {
my $passwordsql;
if ( $dynamicHash == 1 ) {
# Dynamic password hashes
$passwordsql =
$self->dynamic_hash_new_password( $self->dbh, $req->user, $pwd, $table, $userCol, $passwordCol );
$self->dynamic_hash_new_password( $self->dbh, $req->user, $pwd,
$table, $userCol, $passwordCol );
}
else
{
else {
# Static Password hash
$passwordsql = $self->hash_password( "?", $self->conf->{dbiAuthPasswordHash} );
$passwordsql =
$self->hash_password( "?", $self->conf->{dbiAuthPasswordHash} );
}
eval {
......
......@@ -10,12 +10,12 @@ extends 'Lemonldap::NG::Portal::Password::Base';
our $VERSION = '2.0.0';
sub init {1}
sub init { 1 }
sub confirm {1}
sub confirm { 1 }
sub modifyPassword {
PE_PASSWORD_OK
PE_PASSWORD_OK;
}
1;
......@@ -86,9 +86,9 @@ expectAuthenticatedAs( $res, 'french' );
ok( $res = $sp->_get("/sessions/global/$spId"), 'Get UTF-8' );
expectOK($res);
ok( $res = eval { JSON::from_json( $res->[2]->[0] ) }, ' GET JSON' )
or print STDERR $@;
or print STDERR $@;
ok( $res->{cn} eq 'Frédéric Accents', 'UTF-8 values' )
or explain( $res, 'cn => Frédéric Accents' );
or explain( $res, 'cn => Frédéric Accents' );
count(3);
# Logout initiated by SP
......
......@@ -67,6 +67,7 @@ ok( $res->{_session_id} eq $spId, ' Good ID' )
or explain( $res, "_session_id => $spId" );
ok( $res->{uid} eq