Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Maxime Besson
lemonldap-ng
Commits
eb4b7216
Commit
eb4b7216
authored
Apr 02, 2016
by
Yadd
Browse files
#595 in progress
parent
f91910ca
Changes
4
Hide whitespace changes
Inline
Side-by-side
lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm
View file @
eb4b7216
...
...
@@ -66,18 +66,21 @@ has QUERY_STRING => (
reader
=>
'
query
',
trigger
=>
sub
{
my
$self
=
shift
;
$self
->
{
QUERY_STRING
}
=
uri_unescape
(
$self
->
{
QUERY_STRING
}
);
my
@tmp
=
$self
->
{
QUERY_STRING
}
?
split
/&/
,
$self
->
{
QUERY_STRING
}
:
();
foreach
my
$s
(
@tmp
)
{
if
(
$s
=~
/^(.+?)=(.+)$/
)
{
$self
->
{
_params
}
->
{
$
1
}
=
$
2
;
}
else
{
$self
->
{
_params
}
->
{
$s
}
=
1
;
}
}
$self
->
_urlcode2params
(
$self
->
{
QUERY_STRING
}
);
},
);
sub
_urlcode2params
{
my
(
$self
,
$str
)
=
shift
;
my
@tmp
=
$str
?
map
{
uri_unescape
(
$_
)
}
split
(
/&/
,
$str
)
:
();
foreach
my
$s
(
@tmp
)
{
if
(
$s
=~
/^(.+?)=(.+)$/
)
{
$self
->
{
_params
}
->
{
$
1
}
=
$
2
;
}
else
{
$self
->
{
_params
}
->
{
$s
}
=
1
;
}
}
}
*param
=
*params
;
sub
params
{
my
(
$self
,
$key
,
$value
)
=
@_
;
return
$self
->
_params
unless
(
$key
);
...
...
@@ -145,6 +148,17 @@ sub jsonBodyToObj {
return
$self
->
{
body
}
=
$j
;
}
sub
parseBody
{
my
$self
=
shift
;
if
(
$self
->
contentType
=~
/application\/json/
)
{
%
{
$self
->
_params
}
=
(
%
{
$self
->
_params
},
%
{
$self
->
jsonBodyToObj
}
);
}
elsif
(
$self
->
contentType
=~
/^application\/x-www-form-urlencoded/
)
{
$self
->
_urlcode2params
(
$self
->
body
);
}
}
1
;
__END__
...
...
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm
View file @
eb4b7216
...
...
@@ -4,10 +4,77 @@ use strict;
use
Mouse
;
use
Lemonldap::NG::Portal::Main::
Constants
;
use
Lemonldap::NG::Portal::Main::
Request
;
use
MIME::
Base64
;
our
$VERSION
=
'
2.0.0
';
# Auth process
# First process block: check args
# -------------------------------
# For post requests, parse datas
sub
restoreArgs
{
my
(
$self
,
$req
)
=
@_
;
$req
->
parseBody
;
return
(
%
{
$req
->
params
}
?
PE_OK
:
PE_FORMEMPTY
);
}
# Verify url parameter
sub
controlUrl
{
my
(
$self
,
$req
)
=
@_
;
$req
->
datas
->
{
_url
}
||=
'';
if
(
my
$url
=
$req
->
param
('
url
')
)
{
# REJECT NON BASE64 URL except for CAS IssuerDB
if
(
$self
->
get_module
('
issuer
')
ne
"
CAS
"
)
{
if
(
$url
=~
m#[^A-Za-z0-9\+/=]#
)
{
$self
->
lmLog
(
"
Value must be in BASE64 (param: url | value:
$url
)
",
"
warn
"
);
return
PE_BADURL
;
}
$req
->
datas
->
{
urldc
}
=
decode_base64
(
$url
);
$req
->
datas
->
{
urldc
}
=~
s/[\r\n]//sg
;
}
else
{
$req
->
datas
->
{
urldc
}
=
$url
;
}
# For logout request, test if Referer comes from an authorizated site
my
$tmp
=
(
$req
->
param
('
logout
')
?
$ENV
{
HTTP_REFERER
}
:
$req
->
datas
->
{
urldc
}
);
# XSS attack
if
(
$self
->
checkXSSAttack
(
$req
->
param
('
logout
')
?
'
HTTP Referer
'
:
'
urldc
',
$req
->
datas
->
{
urldc
}
)
)
{
delete
$req
->
datas
->
{
urldc
};
return
PE_BADURL
;
}
# Non protected hosts
if
(
$tmp
and
!
$self
->
isTrustedUrl
(
$tmp
)
)
{
$self
->
lmLog
(
"
URL contains a non protected host (param:
"
.
(
$req
->
param
('
logout
')
?
'
HTTP Referer
'
:
'
urldc
'
)
.
"
| value:
$tmp
)
",
"
warn
"
);
delete
$req
->
datas
->
{
urldc
};
return
PE_BADURL
;
}
$req
->
datas
->
{
_url
}
=
$url
;
}
PE_OK
;
}
# Second block: auth process (call auth or userDB object)
# -------------------------------------------------------
sub
extractFormInfo
{
my
$self
=
shift
;
return
$self
->
_authentication
->
extractFormInfo
(
@
_
);
...
...
@@ -23,7 +90,8 @@ sub authenticate {
return
$self
->
_authentication
->
authenticate
(
@
_
);
}
# Session data providing
# Third block: Session data providing
# -----------------------------------
sub
setSessionInfo
{
my
(
$self
,
$req
)
=
@_
;
...
...
@@ -43,7 +111,8 @@ sub setSessionInfo {
$req
->
{
sessionInfo
}
->
{
_utime
}
||=
time
();
$req
->
{
sessionInfo
}
->
{
startTime
}
=
strftime
(
"
%Y%m%d%H%M%S
",
localtime
()
);
$req
->
{
sessionInfo
}
->
{
_lastSeen
}
=
time
()
if
$self
->
conf
->
{
timeoutActivity
};
$req
->
{
sessionInfo
}
->
{
_lastSeen
}
=
time
()
if
$self
->
conf
->
{
timeoutActivity
};
}
# Get environment variables matching exportedVars
...
...
@@ -64,147 +133,147 @@ sub setSessionInfo {
}
sub
setMacros
{
my
(
$self
,
$req
)
=
@_
;
foreach
(
sort
keys
%
{
$self
->
_macros
}
)
{
$req
->
{
sessionInfo
}
->
{
$_
}
=
$self
->
_macros
->
{
$_
}
->
(
$req
);
}
PE_OK
;
my
(
$self
,
$req
)
=
@_
;
foreach
(
sort
keys
%
{
$self
->
_macros
}
)
{
$req
->
{
sessionInfo
}
->
{
$_
}
=
$self
->
_macros
->
{
$_
}
->
(
$req
);
}
PE_OK
;
}
sub
setGroups
{
my
(
$self
,
$req
)
=
@_
;
return
$self
->
_userDB
->
setGroups
(
@
_
);
my
(
$self
,
$req
)
=
@_
;
return
$self
->
_userDB
->
setGroups
(
@
_
);
}
sub
setPersistentSessionInfo
{
my
(
$self
,
$req
)
=
@_
;
my
(
$self
,
$req
)
=
@_
;
# Do not restore infos if session already opened
unless
(
$req
->
{
id
}
)
{
my
$key
=
$req
->
{
sessionInfo
}
->
{
$self
->
conf
->
{
whatToTrace
}
};
# Do not restore infos if session already opened
unless
(
$req
->
{
id
}
)
{
my
$key
=
$req
->
{
sessionInfo
}
->
{
$self
->
conf
->
{
whatToTrace
}
};
return
PE_OK
unless
(
$key
and
length
(
$key
)
);
return
PE_OK
unless
(
$key
and
length
(
$key
)
);
my
$persistentSession
=
$self
->
getPersistentSession
(
$key
);
my
$persistentSession
=
$self
->
getPersistentSession
(
$key
);
if
(
$persistentSession
)
{
$self
->
lmLog
(
"
Persistent session found for
$key
",
'
debug
'
);
foreach
my
$k
(
keys
%
{
$persistentSession
->
data
}
)
{
if
(
$persistentSession
)
{
$self
->
lmLog
(
"
Persistent session found for
$key
",
'
debug
'
);
foreach
my
$k
(
keys
%
{
$persistentSession
->
data
}
)
{
# Do not restore some parameters
next
if
$k
=~
/^_(?:utime|session_(?:u?id|kind))$/
;
$self
->
lmLog
(
"
Restore persistent parameter
$k
",
'
debug
'
);
$req
->
{
sessionInfo
}
->
{
$k
}
=
$persistentSession
->
data
->
{
$k
};
}
}
}
# Do not restore some parameters
next
if
$k
=~
/^_(?:utime|session_(?:u?id|kind))$/
;
$self
->
lmLog
(
"
Restore persistent parameter
$k
",
'
debug
'
);
$req
->
{
sessionInfo
}
->
{
$k
}
=
$persistentSession
->
data
->
{
$k
};
}
}
}
PE_OK
;
PE_OK
;
}
sub
setLocalGroups
{
my
(
$self
,
$req
)
=
@_
;
foreach
(
sort
keys
%
{
$self
->
_groups
}
)
{
if
(
$self
->
_groups
->
{
$_
}
->
(
$req
)
)
)
{
$req
->
{
sessionInfo
}
->
{
groups
}
.=
$self
->
conf
->
{
multiValuesSeparator
}
.
$_
;
$req
->
{
sessionInfo
}
->
{
hGroups
}
->
{
$_
}
->
{
name
}
=
$_
;
}
}
# Clear values separator at the beginning
if
(
$req
->
{
sessionInfo
}
->
{
groups
}
)
{
$req
->
{
sessionInfo
}
->
{
groups
}
=~
s/^\Q$self->conf->{multiValuesSeparator}\E//o
;
}
PE_OK
;
my
(
$self
,
$req
)
=
@_
;
foreach
(
sort
keys
%
{
$self
->
_groups
}
)
{
if
(
$self
->
_groups
->
{
$_
}
->
(
$req
)
)
)
{
$req
->
{
sessionInfo
}
->
{
groups
}
.=
$self
->
conf
->
{
multiValuesSeparator
}
.
$_
;
$req
->
{
sessionInfo
}
->
{
hGroups
}
->
{
$_
}
->
{
name
}
=
$_
;
}
}
# Clear values separator at the beginning
if
(
$req
->
{
sessionInfo
}
->
{
groups
}
)
{
$req
->
{
sessionInfo
}
->
{
groups
}
=~
s/^\Q$self->conf->{multiValuesSeparator}\E//o
;
}
PE_OK
;
}
sub
store
{
my
(
$self
,
$req
)
=
@_
;
# Now, user is authenticated => inform handler
$req
->
userData
(
$req
->
sessionInfo
);
# Create second session for unsecure cookie
if
(
$self
->
conf
->
{
securedCookie
}
==
2
)
{
my
$session2
=
$self
->
getApacheSession
(
undef
,
1
);
my
%infos
=
%
{
$req
->
{
sessionInfo
}
};
$infos
{
_httpSessionType
}
=
1
;
$session2
->
update
(
\
%infos
);
$req
->
{
sessionInfo
}
->
{
_httpSession
}
=
$session2
->
id
;
}
# Main session
my
$session
=
$self
->
getApacheSession
(
$req
->
{
id
},
0
,
$self
->
{
force
}
);
return
PE_APACHESESSIONERROR
unless
(
$session
);
# Compute unsecure cookie value if needed
if
(
$self
->
conf
->
{
securedCookie
}
==
3
)
{
$req
->
{
sessionInfo
}
->
{
_httpSession
}
=
$self
->
conf
->
{
cipher
}
->
encryptHex
(
$self
->
{
id
},
"
http
"
);
}
# Fill session
my
$infos
=
{};
foreach
my
$k
(
keys
%
{
$req
->
{
sessionInfo
}
}
)
{
next
unless
defined
$req
->
{
sessionInfo
}
->
{
$k
};
my
$displayValue
=
$req
->
{
sessionInfo
}
->
{
$k
};
if
(
$self
->
conf
->
{
hiddenAttributes
}
=~
/\b$k\b/
)
{
$displayValue
=
'
****
';
}
$self
->
lmLog
(
"
Store
$displayValue
in session key
$k
",
'
debug
'
);
$self
->
_dump
(
$displayValue
)
if
ref
(
$displayValue
);
$infos
->
{
$k
}
=
$self
->
{
sessionInfo
}
->
{
$k
};
}
$session
->
update
(
$infos
);
PE_OK
;
my
(
$self
,
$req
)
=
@_
;
# Now, user is authenticated => inform handler
$req
->
userData
(
$req
->
sessionInfo
);
# Create second session for unsecure cookie
if
(
$self
->
conf
->
{
securedCookie
}
==
2
)
{
my
$session2
=
$self
->
getApacheSession
(
undef
,
1
);
my
%infos
=
%
{
$req
->
{
sessionInfo
}
};
$infos
{
_httpSessionType
}
=
1
;
$session2
->
update
(
\
%infos
);
$req
->
{
sessionInfo
}
->
{
_httpSession
}
=
$session2
->
id
;
}
# Main session
my
$session
=
$self
->
getApacheSession
(
$req
->
{
id
},
0
,
$self
->
{
force
}
);
return
PE_APACHESESSIONERROR
unless
(
$session
);
# Compute unsecure cookie value if needed
if
(
$self
->
conf
->
{
securedCookie
}
==
3
)
{
$req
->
{
sessionInfo
}
->
{
_httpSession
}
=
$self
->
conf
->
{
cipher
}
->
encryptHex
(
$self
->
{
id
},
"
http
"
);
}
# Fill session
my
$infos
=
{};
foreach
my
$k
(
keys
%
{
$req
->
{
sessionInfo
}
}
)
{
next
unless
defined
$req
->
{
sessionInfo
}
->
{
$k
};
my
$displayValue
=
$req
->
{
sessionInfo
}
->
{
$k
};
if
(
$self
->
conf
->
{
hiddenAttributes
}
=~
/\b$k\b/
)
{
$displayValue
=
'
****
';
}
$self
->
lmLog
(
"
Store
$displayValue
in session key
$k
",
'
debug
'
);
$self
->
_dump
(
$displayValue
)
if
ref
(
$displayValue
);
$infos
->
{
$k
}
=
$self
->
{
sessionInfo
}
->
{
$k
};
}
$session
->
update
(
$infos
);
PE_OK
;
}
sub
buildCookie
{
my
(
$self
,
$req
)
=
@_
;
push
@
{
$req
->
respCookies
},
$self
->
cookie
(
name
=>
$self
->
{
cookieName
},
value
=>
$self
->
{
id
},
domain
=>
$self
->
{
domain
},
path
=>
"
/
",
secure
=>
$self
->
{
securedCookie
},
HttpOnly
=>
$self
->
{
httpOnly
},
expires
=>
$self
->
{
cookieExpiration
},
@
_
,
);
if
(
$self
->
conf
->
{
securedCookie
}
>=
2
)
{
push
@
{
$req
->
respCookies
},
$self
->
cookie
(
name
=>
$self
->
{
cookieName
}
.
"
http
",
value
=>
$self
->
{
sessionInfo
}
->
{
_httpSession
},
domain
=>
$self
->
{
domain
},
path
=>
"
/
",
secure
=>
0
,
HttpOnly
=>
$self
->
{
httpOnly
},
expires
=>
$self
->
{
cookieExpiration
},
@
_
,
);
}
PE_OK
;
my
(
$self
,
$req
)
=
@_
;
push
@
{
$req
->
respCookies
},
$self
->
cookie
(
name
=>
$self
->
{
cookieName
},
value
=>
$self
->
{
id
},
domain
=>
$self
->
{
domain
},
path
=>
"
/
",
secure
=>
$self
->
{
securedCookie
},
HttpOnly
=>
$self
->
{
httpOnly
},
expires
=>
$self
->
{
cookieExpiration
},
@
_
,
);
if
(
$self
->
conf
->
{
securedCookie
}
>=
2
)
{
push
@
{
$req
->
respCookies
},
$self
->
cookie
(
name
=>
$self
->
{
cookieName
}
.
"
http
",
value
=>
$self
->
{
sessionInfo
}
->
{
_httpSession
},
domain
=>
$self
->
{
domain
},
path
=>
"
/
",
secure
=>
0
,
HttpOnly
=>
$self
->
{
httpOnly
},
expires
=>
$self
->
{
cookieExpiration
},
@
_
,
);
}
PE_OK
;
}
sub
cookie
{
my
(
$self
,
%h
)
=
@_
;
my
@res
;
$req
[
0
]
=
"
$h
{name}
"
or
die
("
name required
");
my
$res
[
0
]
.=
"
=
$h
{value}
";
foreach
(
qw(domain path expires max_age)
)
{
my
$f
=
$_
;
s/_/-/g
;
push
@res
,
"
$_
=
$h
{
$f
}
"
if
(
$h
{
$f
});
}
return
join
('
;
',
@res
);
my
(
$self
,
%h
)
=
@_
;
my
@res
;
$req
[
0
]
=
"
$h
{name}
"
or
die
("
name required
");
my
$res
[
0
]
.=
"
=
$h
{value}
";
foreach
(
qw(domain path expires max_age)
)
{
my
$f
=
$_
;
s/_/-/g
;
push
@res
,
"
$_
=
$h
{
$f
}
"
if
(
$h
{
$f
}
);
}
return
join
(
'
;
',
@res
);
}
1
;
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm
View file @
eb4b7216
...
...
@@ -5,12 +5,22 @@ use Mouse;
extends
'
Lemonldap::NG::Common::PSGI::Request
';
# List of methods to call
has
steps
=>
(
is
=>
'
rw
'
);
has
datas
=>
(
is
=>
'
rw
'
);
# Datas shared between methods
has
datas
=>
(
is
=>
'
rw
',
default
=>
sub
{
{}
}
);
# Session datas when created
has
id
=>
(
is
=>
'
rw
'
);
has
sessionInfo
=>
(
is
=>
'
rw
'
);
# Response cookies (list of strings built by cookie())
has
respCookies
=>
(
is
=>
'
rw
'
);
# Template to display (if not defined, login or menu)
has
template
=>
(
is
=>
'
rw
'
);
sub
wantJSON
{
return
$_
[
0
]
->
accept
=~
m#(?:application|text)/json#
?
1
:
0
;
}
...
...
lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm
View file @
eb4b7216
...
...
@@ -2,17 +2,17 @@
# Serve request part of Lemonldap::NG portal
#
# Methods:
# - handler():
verify that portal configuration is the same that the
#
underlying handler configuration before launching
#
Lemonldap::NG::Common::PSGI::Router::handler() (which parse
#
routes)
# - handler(): verify that portal configuration is the same that the
# underlying handler configuration before launching
# Lemonldap::NG::Common::PSGI::Router::handler() (which parse
# routes)
#
# Entry points:
# - "/test":
*
authenticated() for already authenticated users
#
*
pleaseAuth() for others
# - "/":
*
login() ~first access
#
*
postLogin(), same for POST requests
#
*
authenticatedRequest() for authenticated users
# - "/test":
-
authenticated() for already authenticated users
#
-
pleaseAuth() for others
# - "/":
-
login() ~first access
#
-
postLogin(), same for POST requests
#
-
authenticatedRequest() for authenticated users
package
Lemonldap::NG::Portal::Main::
Run
;
use
strict
;
...
...
@@ -61,9 +61,9 @@ sub login {
return
$req
->
do
(
$req
,
[
'
rememberArgs
',
@
{
$self
->
beforeAuth
},
&authProcess
,
@
{
$self
->
betweenAuthAndDatas
},
&sessionDatas
,
@
{
$self
->
afterdatas
},
'
controlUrl
',
@
{
$self
->
beforeAuth
},
&authProcess
,
@
{
$self
->
betweenAuthAndDatas
},
&sessionDatas
,
@
{
$self
->
afterdatas
},
]
);
}
...
...
@@ -73,7 +73,7 @@ sub postLogin {
return
$req
->
do
(
$req
,
[
'
restoreArgs
',
@
{
$self
->
beforeAuth
},
'
restoreArgs
',
'
controlUrl
'
@
{
$self
->
beforeAuth
},
&authProcess
,
@
{
$self
->
betweenAuthAndDatas
},
&sessionDatas
,
@
{
$self
->
afterdatas
},
]
...
...
@@ -109,7 +109,7 @@ sub do {
}
else
{
if
(
$err
)
{
return
$self
->
sendHtml
(
$req
,
'
login
.tpl
'
);
return
$self
->
sendHtml
(
$req
,
$req
->
template
||
'
login
'
);
}
else
{
return
$self
->
autoRedirect
(
$req
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment