APM Sharepoint authentication v2
Problem this snippet solves:
This new version of irule supports NTLM auth (mandatory for Onedrive Apps)
APM is a great authentication service but it does it only with forms.
The default behavior is to redirect user to /my.policy to process VPE. this redirect is only supported for GET method.
Sharepoint provide 3 different access types:
browsing web site with a browser
- Editing documents with Office
- connect to One Drive on premise from PC and mobiles
- browser folder with webdav client (or editing documents with libreoffice through webdav protocol)
This irule display best authentication method for each of these access types:
- browsers authenticate with default authentication method (form based authentication)
- Microsoft office authenticate with Form based authentication (with support of MS-OFBA protocol)
- Libreoffice and webdav clients authenticate with 401 basic authentication (NTLM and Basic)
- Form based authentication (browser and Microsoft office) is compatible (validated for one customer) with SAML authentication
- NTLM auth for Onedrive mobile applications
Editing documents is managed with a persistent cookie expiring after 5 minutes. to be shared between IE and Office, it requires :
- cookie is persistent (expiration date instead of deleted at the end of session)
- web site defined as "trusted sites" in IE.
How to use this snippet:
install this irule and enable it on the VS.
In the first HTTP_REQUEST event, configure authentication mode list by setting the AUTHENTICATION_MODE variable
Set authentication mode list supported. possible values are :
- form :default Form based authentication
- msofba : Microsoft Office Form Based Authentication for Office and Onedrive apps
-
persist : Add persistent cookie to recover closed session. this function is only supported by form and msofba authentications.
- --> persist word must be set after authentication mode : ex : {form persist} or {msofba persist}
-
basic : Basic Authentication
-
ntlm : NTLM Authentication
-
negotiate : Kerberos / SPNEGO authentication : Not supported yet by this irule
- --> basic, ntm and negotiate can be set together. ex: {negotiate ntlm basic} {ntlm basic}
-
deny : send a 403 response code to deny the request
-
disable : disable APM authentication
Code :
when RULE_INIT { #If NTLM Auth is defined below, define the ECA_METADATA_ARG with your NTLM profile and enable eca profile in virtual server configuration with tmsh command # modify ltm virtual [virtual name] profile add {eca} set static::ECA_METADATA_ARG "select_ntlm:/Common/NTLM-Auth" set static::session_restore_aes_key "AES 256 affeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe" ;# AES Key to protect and validate recovery data # Define required APM variables stored in the restore cookie to create new session with same security level. set static::session_restore_variables { session.ui.lang session.logon.last.username session.logon.last.logonname session.logon.last.krbdomain session.logon.last.domain session.krbsso.last.domain session.krbsso.last.username session.assigned.acls session.logon.last.domain session.sso.token.last.username session.user.sessiontype } # Cookie expire in 2 hours for the test... set static::session_restore_timeout 172800 ;### 7200 / 172800 } when CLIENT_ACCEPTED { set last_ua_agent "init" # Set addtional HTTP headers in HTTP authentication responses set ADDITIONAL_AUTH_HEADERS "MicrosoftSharePointTeamServices 15.0.0.4763" } when HTTP_REQUEST { #################################### Authentication method selection ##################################################### # Set authentication mode list supported. possible values are # form :default Form based authentication # msofba : Microsoft Office Form Based Authentication for Office and Onedrive apps # persist : Add persistent cookie to recover closed session. this function is only supported by form and msofba authentications. # --> persist word must be set after authentication mode : ex : {form persist} or {msofba persist} # basic : Basic Authentication # ntlm : NTLM Authentication # negotiate : Kerberos / SPNEGO authentication : Not supported yet by this irule # --> basic, ntm and negotiate can be set together. ex: {negotiate ntlm basic} {ntlm basic} # deny : send a 403 response code to deny the request # disable : disable APM authentication # Disable Authentication for Internal networks #if { [IP::addr [IP::client_addr]/25 equals 1.1.1.0] or [IP::addr [IP::client_addr]/25 equals 2.2.2.0] } { # set AUTHENTICATION_MODE {disable} # ASM::disable # return #} #log local0. [HTTP::header "User-Agent"] if { $last_ua_agent equals [set last_ua_agent [HTTP::header value "User-Agent"]] } { # Do nothing, keep previous request authschema value } 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 AUTHENTICATION_MODE {msofba} } else { switch -glob -- [string tolower [HTTP::header "User-Agent"]] { "*microsoft office *ios*" - "*onedriveiosapp*" - "onedrive/*darwin*" { # NTLM is the only one supported for onedrive mobile set AUTHENTICATION_MODE {ntlm basic} #set AUTHENTICATION_MODE {deny} } "*microsoft office onedrive*" - "*microsoft onedrive*" - "*microsoft office skydrive*" - "*microsoft office syncproc*" - "*microsoft office upload center*" - "*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 AUTHENTICATION_MODE {msofba} #set AUTHENTICATION_MODE {ntlm basic} } "*ms frontpage*" { # Legacy client detected set AUTHENTICATION_MODE {ntlm basic} #set AUTHENTICATION_MODE {deny} } "*mozilla*" - "*opera*" { # Regular web browser detected. set AUTHENTICATION_MODE {form} } default { set AUTHENTICATION_MODE {ntlm basic} #set AUTHENTICATION_MODE {msofba} } } #log local0. "[IP::remote_addr] : [string tolower [HTTP::header "User-Agent"]] : $AUTHENTICATION_MODE : [HTTP::cookie value MRHSession] : [HTTP::cookie value MRHSession_R]" } #################################### end of Authentication method selection ############################################## } priority 900 when RULE_INIT { set static::AUTH_POLICY_FAILED "policy_failed" set static::AUTH_POLICY_SUCCEED "policy_succeed" set static::AUTH_POLICY_DONE_WAIT_SEC 5 set static::AUTH_FIRST_BIG_POST_CONTENT_LEN 640000 set static::AUTH_POLICY_RESULT_POLL_INTERVAL 100 set static::AUTH_POLICY_RESULT_POLL_MAXRETRYCYCLE 100 set static::AUTH_ACCESS_USERKEY_TBLNAME "auth_access_userkey" set static::AUTH_ACCESS_LOG_PREFIX "01490000:7:" set static::AUTH_ACCESS_DEL_COOKIE_HDR_VAL "MRHSession=deleted; \ expires=Thu, 01-Jan-1970 00:00:01 GMT;\ path=/" } when CLIENT_ACCEPTED { set clientless_mode 0 set inject_session_cookie "" set inject_recover_cookie 0 if { ! [ info exists ADDITIONAL_AUTH_HEADERS ] } { set ADDITIONAL_AUTH_HEADERS "" } } when HTTP_REQUEST { set inject_session_cookie "" if { ! [ info exists f_ntlm_auth_succeed ] } { set f_ntlm_auth_succeed 0 } if { ! [ info exists sid_cache ] } { set sid_cache "" } if { ! [ info exists PROFILE_POLICY_TIMEOUT ] } { set PROFILE_POLICY_TIMEOUT [PROFILE::access access_policy_timeout] } if { ! [ info exists PROFILE_MAX_SESS_TIMEOUT ] } { set PROFILE_MAX_SESS_TIMEOUT [PROFILE::access max_session_timeout] } if { ! [ info exists src_ip ] } { set src_ip [IP::remote_addr] } if { ! [ info exists PROFILE_RESTRICT_SINGLE_IP ] } { set PROFILE_RESTRICT_SINGLE_IP [PROFILE::access restrict_to_single_client_ip] } set persisted_session_timeout [PROFILE::access inactivity_timeout] set http_method [HTTP::method] set http_uri [HTTP::uri] set http_content_len [HTTP::header Content-Length] set MRHSession_cookie [HTTP::cookie value MRHSession] if { ! [ info exists AUTHENTICATION_MODE ] } { set AUTHENTICATION_MODE {form} } switch -- [lindex $AUTHENTICATION_MODE 0] { "disable" { #################################### APM Disable ######################################################################### # disable APM and leave irule if mode is set to disable ACCESS::disable return } "form" { #################################### Form based authentication ########################################################### # Leave irule if authentication mode is set to default form base authentication if {[lindex $AUTHENTICATION_MODE 1] equals "persist"} { set inject_recover_cookie 1} else {set inject_recover_cookie 0} set apm_sessionid [HTTP::cookie value "MRHSession"] if {![HTTP::cookie exists MRHSession] || !($inject_recover_cookie && [HTTP::cookie exists MRHSession_R])} {return} } "deny" { #################################### Deny Request ######################################################################## # Respond with 403 response code and "Access Denied" content if mode is set to deny HTTP::respond 403 -version "1.1" \ content {Access Denied.} \ noserver \ "Content-Type" "text/html" \ "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 } default { #################################### All other authentication methods ##################################################### # provision response Headers for specific authentication set httpheaders "$ADDITIONAL_AUTH_HEADERS Set-Cookie \"MRHSession=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/\" Connection close" set httpcontent "ForbidenAuthentication\\ Required" set httpcode 401 foreach authvalue $AUTHENTICATION_MODE { switch $authvalue { basic { append httpheaders " WWW-Authenticate \"Basic realm=\\\"[HTTP::host]\\\"\"" } ntlm { append httpheaders " WWW-Authenticate NTLM" } negotiate { # Authentication method negociate not managed by this irule yet append httpheaders " WWW-Authenticate Negotiate" } msofba { #log local0. [HTTP::cookie value MRHSession_SP] if {[lindex $AUTHENTICATION_MODE 1] equals "persist" && [HTTP::cookie exists MRHSession_R]} { set persisted_session_timeout 300 } elseif {[HTTP::path] ne "/vdesk/ms-ofba-form"} { append httpheaders " \"Content-Type\"\ \"text/html\"" append httpheaders " X-FORMS_BASED_AUTH_REQUIRED"\ "https://[getfield [HTTP::host] ":" 1]/vdesk/ms-ofba-form?mode=[lindex $AUTHENTICATION_MODE 1]" append httpheaders " X-FORMS_BASED_AUTH_RETURN_URL"\ "https://[getfield [HTTP::host] ":" 1]/vdesk/ms-ofba-completed" append httpheaders " X-FORMS_BASED_AUTH_DIALOG_SIZE"\ "800x600" set httpcontent "ForbidenAccess\\ Denied.\\ Make\\ sure\\ that\\ your\\ client\\ is\\ correctly\\ configured.\\ See\\ https://support.microsoft.com/en-us/kb/932118\\ for\\ further\\ information." set httpcode 403 } } } } } } #################################### NTLM already authenticated connection ############################################### if {$f_ntlm_auth_succeed} { # enable ECA profile for already NTLM authenticated connections and ignore this irule event ECA::enable ECA::select $static::ECA_METADATA_ARG return } #################################### Valid session request : MHRSession Cookie ########################################### if { ( [set apm_sessionid [HTTP::cookie value "MRHSession"]] ne "" ) and ( [ACCESS::session exists -state_allow $apm_sessionid] ) } then { # Allow the successfully pre authenticated request to pass return #################################### Valid session request : MHRSession_R Cookie ######################################## ### This cokie is inserted to allow a user to log with recorded data stored on a encrypted cookie } elseif {([lindex $AUTHENTICATION_MODE 0] ne "form") and ( [set apm_sessionid [HTTP::cookie value "MRHSession_SP"]] ne "" ) and ( [ACCESS::session exists -state_allow $apm_sessionid] ) } then { #################################### Valid session request : MHRSession_SP Cookie ######################################## # Check if persistent APM session cookie is present and valid # Restore APM session cookie value HTTP::cookie insert name "MRHSession" value $apm_sessionid set inject_session_cookie $apm_sessionid # Allow the successfully pre authenticated request to pass return } elseif { [lindex $AUTHENTICATION_MODE 1] equals "persist" && [HTTP::cookie exists MRHSession_R] and ( [set session_restore_data [AES::decrypt $static::session_restore_aes_key [b64decode [HTTP::cookie value MRHSession_R]]]] ne "" )} { array set restore_data $session_restore_data if {$restore_data(timeout) > [clock seconds] } { set user_key "persist.[PROFILE::access name].$restore_data(session.logon.last.username)" if {[set apm_sessionid [table lookup -subtable APMSessionRestore $user_key]] != "" && ( [ACCESS::session exists -state_allow $apm_sessionid] ) } { #log local0. "session recover by table" } elseif { ([ llength [set cookie_list [ ACCESS::user getsid $user_key ] ] ] != 0) and [set apm_sessionid [ ACCESS::user getkey [ lindex $cookie_list 0 ] ] ] ne ""} { #log local0. "session recover by cookie list" } else { #log local0. "new session" if { [HTTP::header value "Accept-Language"] eq "" } then { # A "Accept-language" header is not present. Injecting language code = none HTTP::header insert "Accept-Language" "none" } set apm_sessionid [ACCESS::session create -timeout $persisted_session_timeout] ACCESS::session data set -sid $apm_sessionid "session.policy.result" "allow" foreach session_variable [lsearch -all -inline -not -exact [array names restore_data] timeout] { ACCESS::session data set -sid $apm_sessionid $session_variable $restore_data($session_variable) #log local0.debug "Adding $session_variable = $restore_data($session_variable)" } ACCESS::session data set -sid $apm_sessionid ".session.assigned.uuid" "tmm.uuid.$user_key" ACCESS::session data set -sid $apm_sessionid "session.user.uuid" $user_key } HTTP::cookie insert name "MRHSession" value $apm_sessionid set inject_session_cookie $apm_sessionid table set -subtable "APMSessionRestore" $user_key $apm_sessionid $persisted_session_timeout indef unset restore_data user_key return } } #################################### Request with valid Authorization Header ############################################ ### convert authentication header to be managed by APM if { [ llength [set auth_data [split [HTTP::header Authorization] " "]] ] == 2 } { if {[lsearch -exact $AUTHENTICATION_MODE [set authvalue [string tolower [ lindex $auth_data 0]]]] ne -1} { switch $authvalue { "ntlm" { ECA::enable ECA::select $static::ECA_METADATA_ARG } "basic" { 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 { $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) set clientless_mode 1 } unset clientless } "negotiate" { #log local0. [getfield [HTTP::header Authorization] " " 2] #set clientless(insert_mode) 1 #set clientless(authparam) [getfield [HTTP::header Authorization] " " 2] #log local0. $clientless(authparam) #log local0. [string length $clientless(authparam)] #set clientless(decode) [b64decode $clientless(authparam)] ##log local0. [sha256 "$clientless(decode)"] #binary scan [sha256 "$clientless(decode)"] H* clientless(hash) #log local0. $clientless(hash) #set user_key "$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 # set clientless_mode 1 # } # unset clientless } default { #other authentication methodes are not managed by this irule yet } } } #################################### Redirect unmanaged requests with supported authentication method ################## } else { eval HTTP::respond $httpcode -version 1.1 content $httpcontent noserver $httpheaders return } } when HTTP_RESPONSE { # Insert persistent cookie for html content type and private session if { [HTTP::header "Content-Type" ] contains "text/html" && [info exists "apm_sessionid"]} { HTTP::cookie remove MRHSession_SP HTTP::cookie insert name MRHSession_SP value $apm_sessionid path "/" HTTP::cookie expires MRHSession_SP 300 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 ne "") } { HTTP::cookie insert name MRHSession value $inject_session_cookie path "/" HTTP::cookie secure MRHSession enable #log local0. "injected $inject_session_cookie" } if { $inject_recover_cookie } then { # Insert APM recover session cookie into HTTP response. set session_restore_data "[clock seconds] [ACCESS::session data get "session.logon.last.username"]" foreach session_variable $static::session_restore_variables { if { [set session_variable_value [ACCESS::session data get $session_variable]] ne "" } then { lappend session_restore_data "$session_variable=$session_variable_value" } } HTTP::header insert "Set-Cookie" "MRHSession_R=[b64encode [AES::encrypt $static::session_restore_aes_key $session_restore_data]];Path=/;Secure;HttpOnly" set inject_recover_cookie 0 } if {[HTTP::header exists "Transfer-Encoding"]} { HTTP::payload rechunk } } when ACCESS_SESSION_STARTED { if {[set landinguri [ACCESS::session data get session.server.landinguri]] equals "/vdesk/ms-ofba-form?mode=persist" } { ACCESS::session data set session.server.landinguri "/vdesk/AddPersistentCookie?url=[b64encode "/vdesk/ms-ofba-completed"]" } elseif {([info exists "inject_recover_cookie"])} { ACCESS::session data set session.server.landinguri "/vdesk/AddPersistentCookie?url=[b64encode [ACCESS::session data get session.server.landinguri]]" ACCESS::session data set session.inactivity_timeout 300 } if {([info exists "clientless_mode"])} { ACCESS::session data set session.clientless $clientless_mode if {$clientless_mode} { ACCESS::session data set session.inactivity_timeout 300 if {[HTTP::header Authorization] starts_with "Negotiate"}{ ACCESS::session data set session.logon.last.authtype "Negotiate" ACCESS::session data set session.logon.last.authparam [getfield [HTTP::header Authorization] " " 2] } } } if { [ info exists user_key ] } { ACCESS::session data set "session.user.uuid" $user_key } } when ACCESS_POLICY_COMPLETED { if { ! [ info exists user_key ] } { return } set user_key_value "" set f_delete_session 0 set policy_result [ACCESS::policy result] set sid [ ACCESS::session sid ] switch $policy_result { "allow" { set user_key_value $sid set sid_cache $user_key_value log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Result: Allow: $user_key" log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX sid = $sid" } "deny" { eval ACCESS::respond 401 -version 1.1 content {ForbidenAuthentication\ Required} noserver $httpheaders set f_delete_session 1 } default { ACCESS::respond 503 content $static::actsync_503_http_body Connection Close log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Got unsupported policy result for $user_key ($sid)" set f_delete_session 1 } } if { $f_ntlm_auth_succeed == 1 } { if { $user_key_value != "" } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Setting $user_key => $static::AUTH_POLICY_SUCCEED" table set -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME $user_key $static::AUTH_POLICY_SUCCEED } else { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Setting $user_key => $static::AUTH_POLICY_FAILED $static::AUTH_POLICY_DONE_WAIT_SEC $static::AUTH_POLICY_DONE_WAIT_SEC in table $static::AUTH_ACCESS_USERKEY_TBLNAME" table set -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME $user_key $static::AUTH_POLICY_FAILED $static::AUTH_POLICY_DONE_WAIT_SEC $static::AUTH_POLICY_DONE_WAIT_SEC } } if { $f_delete_session == 1 } { ACCESS::session remove set f_delete_session 0 log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Removing the session for $user_key." } } when ACCESS_ACL_ALLOWED { switch -glob -- [string tolower [HTTP::path]] { "/vdesk/addpersistentcookie" { set cookie_expire_absolute [expr {[clock seconds] + $static::session_restore_timeout}] set cookie_expire_date [clock format $cookie_expire_absolute -format "%a, %d-%b-%Y %H:%M:%S GMT" -gmt true] set session_restore_data "timeout $cookie_expire_absolute" foreach session_variable $static::session_restore_variables { if { [set session_variable_value [ACCESS::session data get $session_variable]] ne "" } then { lappend session_restore_data $session_variable $session_variable_value } } set cookie [format "MRHSession_R=%s; path=/; expires=%s;Secure; HttpOnly" [b64encode [AES::encrypt $static::session_restore_aes_key $session_restore_data]] $cookie_expire_date] ACCESS::respond 302 noserver Location [b64decode [URI::query [HTTP::uri] url]] "Set-Cookie" $cookie } "/vdesk/ms-ofba-form" { ACCESS::respond 302 noserver Location "/vdesk/ms-ofba-completed" } "/vdesk/ms-ofba-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" "Set-Cookie" "MRHSession_R=deleted;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;secure" event disable TCP::close 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 "/" "Set-Cookie" "MRHSession_R=deleted;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;secure" event disable TCP::close return } } default { # No Actions } } } when ECA_REQUEST_ALLOWED { set f_ntlm_auth_succeed 1 if { $MRHSession_cookie == "" } { # Retrieve from SID cache set MRHSession_cookie $sid_cache HTTP::cookie insert name MRHSession value $sid_cache } if { $MRHSession_cookie != "" } { # Destroy session ID cache. This client should not need session ID cache if { ($sid_cache != "") && ($sid_cache != $MRHSession_cookie) } { set sid_cache "" } if { [ ACCESS::session exists -state_allow $MRHSession_cookie ] } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX HTTP *VALID* MRHSession cookie: $MRHSession_cookie" # Default profile access setting is false if { $PROFILE_RESTRICT_SINGLE_IP == 0 } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Release the request" return } elseif { [ IP::addr $src_ip equals [ ACCESS::session data get -sid $MRHSession_cookie "session.user.clientip" ] ] } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX source IP matched. Release the request" return } else { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX source IP does not matched" } } else { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX HTTP *INVALID* MRHSession cookie: $MRHSession_cookie" } } set MRHSession "" set sid_cache "" HTTP::cookie remove MRHSession # Build user_key set user_key {} append user_key [string tolower [ECA::username]] "@" [ string tolower [ECA::domainname] ] if { $PROFILE_RESTRICT_SINGLE_IP == 0 } { append user_key ":" $src_ip } append user_key ":" [ECA::client_machine_name] set apm_cookie_list [ ACCESS::user getsid $user_key ] if { [ llength $apm_cookie_list ] != 0 } { set MRHSession_cookie [ ACCESS::user getkey [ lindex $apm_cookie_list 0 ] ] if { $MRHSession_cookie != "" } { set sid_cache $MRHSession_cookie HTTP::cookie insert name MRHSession value $MRHSession_cookie log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX APM Cookie found: $sid_cache" return } } unset apm_cookie_list set try 1 set start_policy_str $src_ip append start_policy_str [TCP::client_port] while { $try <= $static::AUTH_POLICY_RESULT_POLL_MAXRETRYCYCLE } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX NO APM Cookie found" log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Trying #$try for $http_method $http_uri $http_content_len" if { $http_content_len > $static::AUTH_FIRST_BIG_POST_CONTENT_LEN } { # Wait at below } else { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX EXEC: table set -notouch -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME -excl $user_key $start_policy_str $PROFILE_POLICY_TIMEOUT $PROFILE_MAX_SESS_TIMEOUT" set policy_status [table set -notouch -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME -excl $user_key $start_policy_str $PROFILE_POLICY_TIMEOUT $PROFILE_MAX_SESS_TIMEOUT] log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX DONE: table set -notouch -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME -excl $user_key $start_policy_str $PROFILE_POLICY_TIMEOUT $PROFILE_MAX_SESS_TIMEOUT" if { $policy_status == $start_policy_str } { # ACCESS Policy has not started. Start one HTTP::header insert "clientless-mode" 1 set clientless_mode 1 break } elseif { $policy_status == $static::AUTH_POLICY_SUCCEED } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX table is out-of-sync retry" table delete -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME $user_key continue } elseif { $policy_status == $static::AUTH_POLICY_FAILED } { ACCESS::disable TCP::close return } # Wait at below } log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Waiting $static::AUTH_POLICY_RESULT_POLL_INTERVAL ms for $http_method $http_uri" # Touch the entry table table lookup -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME $user_key after $static::AUTH_POLICY_RESULT_POLL_INTERVAL set apm_cookie_list [ ACCESS::user getsid $user_key ] if { [ llength $apm_cookie_list ] != 0 } { set MRHSession_cookie [ ACCESS::user getkey [ lindex $apm_cookie_list 0 ] ] if { $MRHSession_cookie != "" } { set sid_cache $MRHSession_cookie HTTP::cookie insert name MRHSession value $MRHSession_cookie log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX APM Cookie found: $sid_cache" return } } incr try } if { $try > $static::AUTH_POLICY_RESULT_POLL_MAXRETRYCYCLE } { log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Policy did not finish in [ expr { $static::AUTH_POLICY_RESULT_POLL_MAXRETRYCYCLE * $static::AUTH_POLICY_RESULT_POLL_INTERVAL } ] ms. Close connection for $http_method $http_uri" table delete -subtable $static::AUTH_ACCESS_USERKEY_TBLNAME $user_key ACCESS::disable TCP::close return } log -noname accesscontrol.local1.debug "$static::AUTH_ACCESS_LOG_PREFIX Releasing request $http_method $http_uri" unset try unset start_policy_str } when ECA_REQUEST_DENIED { log local0. "User [ECA::username]@[ECA::domainname], Client Machine [ECA::client_machine_name], Auth Status [ECA::status]" set f_ntlm_auth_succeed 0 }
Tested this on version:
11.5- Stanislas_Piro2Cumulonimbus
This code was developed for Office 2016 clients and seems to get some issues with office 2019 clients.