APM Sharepoint authentication
Problem this snippet solves: Updated version to support Webdav with windows explorer after Nicolas's comment.
APM is a great authentication service but it does it only with forms.
The default be...
Published Apr 20, 2016
Version 1.0Stanislas_Piro2
Cumulonimbus
Joined January 04, 2011
Stanislas_Piro2
Cumulonimbus
Joined January 04, 2011
Stanislas_Piro2
Sep 15, 2016Cumulonimbus
Hi Kai,
I followed all your advices (except lockout, One solution instead of blocking with table can be deleting in ACCESS_POLICY_COMPLETED sessions of user with same username if VPE lockout occurs)
here is the new version :
when RULE_INIT {
set static::Basic_Realm_Text "SharePoint Authentication"
}
when CLIENT_ACCEPTED {
set inject_session_cookie 0
set last_ua_agent "init"
}
when HTTP_REQUEST {
if { ! [ info exists SP_PROFILE_RESTRICT_SINGLE_IP ] } {
set SP_PROFILE_RESTRICT_SINGLE_IP [PROFILE::access restrict_to_single_client_ip]
}
Identify User-Agents type
if { $last_ua_agent equals [set last_ua_agent [HTTP::header value "User-Agent"]] } {
Do nothing, keep previous request authschema value
log local0. $last_ua_agent
} elseif {[HTTP::header exists "X-FORMS_BASED_AUTH_ACCEPTED"] && (([HTTP::header "X-FORMS_BASED_AUTH_ACCEPTED"] equals "t") || ([HTTP::header "X-FORMS_BASED_AUTH_ACCEPTED"] equals "f"))} {
set clientless_mode 0; set form_mode 1
} else {
set clientless_mode 0
set form_mode 0
switch -glob -- [string tolower [HTTP::header "User-Agent"]] "*office protocol discovery*" - \
"*microsoft office*" - \
"*microsoft data access internet publishing provider*" - \
"*non-browser*" - \
"msoffice 12*" - \
"*microsoft-webdav-miniredir*" - \
{*ms frontpage 1[23456789]*} {
Implicit MSOFBA support detected.
set form_mode 1
} "*ms frontpage*" {
Legacy client detected
set clientless_mode 1
} "*mozilla*" - \
"*opera*" {
Regular web browser detected.
set clientless_mode 0
} default {
set clientless_mode 1
}
}
if { $clientless_mode || $form_mode } {
if { ( [set sessionid [HTTP::cookie value "MRHSession"]] ne "" ) and ( [ACCESS::session exists -state_allow $sessionid] ) } then {
Allow the successfully pre authenticated request to pass
return
} else {
Check if persistent APM session cookie is present and valid
if { ( [set sessionid [HTTP::cookie value "MRHSession_SP"]] ne "" ) and ( [ACCESS::session exists -state_allow $sessionid] ) } then {
Restore APM session cookie value
if { [catch {HTTP::cookie insert name "MRHSession" value $sessionid} ] } {log local0. "[IP::client_addr]:[TCP::client_port] : TCL error on HTTP cookie insert MRHSession : URL : [HTTP::host][HTTP::path] - Headers : [HTTP::request]"} else {return}
HTTP::cookie insert name "MRHSession" value $sessionid
set inject_session_cookie 1
Allow the successfully pre authenticated request to pass
return
}
}
} else {
set sessionid [HTTP::cookie value "MRHSession"]
return
}
if { $clientless_mode } {
if { [ string match -nocase {basic *} [HTTP::header Authorization] ] == 1 } {
set clientless(insert_mode) 1
set clientless(src_ip) [IP::remote_addr]
set clientless(username) [ string tolower [HTTP::username] ]
set clientless(password) [HTTP::password]
if { $SP_PROFILE_RESTRICT_SINGLE_IP == 0 } {
binary scan [md5 "$clientless(password)"] H* clientless(hash)
} else {
binary scan [md5 "$clientless(password)$clientless(src_ip)"] H* clientless(hash)
}
set user_key "$clientless(username).$clientless(hash)"
set clientless(cookie_list) [ ACCESS::user getsid $user_key ]
if { [ llength $clientless(cookie_list) ] != 0 } {
set clientless(cookie) [ ACCESS::user getkey [ lindex $clientless(cookie_list) 0 ] ]
if { $clientless(cookie) != "" } {
HTTP::cookie insert name MRHSession value $clientless(cookie)
set clientless(insert_mode) 0
}
}
if { $clientless(insert_mode) } {
HTTP::header insert "clientless-mode" 1
HTTP::header insert "username" $clientless(username)
HTTP::header insert "password" $clientless(password)
}
unset clientless
} else {
HTTP::respond 401 noserver WWW-Authenticate "Basic realm=\"$static::Basic_Realm_Text\"" Set-Cookie "MRHSession=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/" Connection close
return
}
} elseif {$form_mode && [HTTP::path] ne "/sp-msofba-form"}{
HTTP::respond 403 -version "1.1" \
content "Access Denied. Make sure that your client is correctly configured. See https://support.microsoft.com/en-us/kb/932118 for further information." \
noserver \
"Content-Type" "text/html" \
"X-FORMS_BASED_AUTH_REQUIRED" "https://[getfield [HTTP::host] ":" 1]/sp-msofba-form" \
"X-FORMS_BASED_AUTH_RETURN_URL" "https://[getfield [HTTP::host] ":" 1]/sp-msofba-completed" \
"X-FORMS_BASED_AUTH_DIALOG_SIZE" "800x600" \
"Set-Cookie" "MRHSession=deleted;path=/;secure" \
"Set-Cookie" "LastMRH_Session=deleted;path=/;secure" \
"Set-Cookie" "MRHSession=deleted; expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;secure" \
"Set-Cookie" "LastMRH_Session=deleted; expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;secure"
return
}
}
when HTTP_RESPONSE {
Insert persistent cookie for html content type and private session
if { [HTTP::header "Content-Type" ] contains "text/html" } {
HTTP::cookie remove MRHSession_SP
HTTP::cookie insert name MRHSession_SP value $sessionid path "/"
HTTP::cookie expires MRHSession_SP 120 relative
HTTP::cookie secure MRHSession_SP enable
}
Insert session cookie if session was recovered from persistent cookie
if { ([info exists "inject_session_cookie"]) && ($inject_session_cookie) } {
HTTP::cookie insert name MRHSession value $sessionid path "/"
HTTP::cookie secure MRHSession enable
}
}
when ACCESS_SESSION_STARTED {
if {([info exists "clientless_mode"])} {
ACCESS::session data set session.clientless $clientless_mode
}
if { [ info exists user_key ] } {
ACCESS::session data set "session.user.uuid" $user_key
}
}
when ACCESS_POLICY_COMPLETED {
if { ([info exists "clientless_mode"]) && ($clientless_mode) && ([ACCESS::policy result] equals "deny") } {
set min "[PROFILE::access min_failure_delay]000"
set max "[PROFILE::access max_failure_delay]000"
after [expr {int(rand() * ($max + 1 - $min)) + $min}]
ACCESS::respond 401 noserver WWW-Authenticate "Basic realm=\"$static::Basic_Realm_Text\"" Connection close
unset min max
ACCESS::session remove
}
}
when ACCESS_ACL_ALLOWED {
switch -glob [string tolower [HTTP::path]] {
"/sp-msofba-form" {
ACCESS::respond 302 noserver Location "/sp-msofba-completed"
}
"/sp-msofba-completed" {
ACCESS::respond 200 content {
Authenticated
Good Work, you are Authenticated
} noserver
}
"*/signout.aspx" {
Disconnect session and redirect to APM logout Page
ACCESS::respond 302 noserver Location "/vdesk/hangup.php3"
return
}
"/_layouts/accessdenied.aspx" {
Disconnect session and redirect to APM Logon Page
if {[string tolower [URI::query [HTTP::uri] loginasanotheruser]] equals "true" } {
ACCESS::session remove
ACCESS::respond 302 noserver Location "/"
return
}
}
default {
No Actions
}
}
}