Forum Discussion
Drew_24528
Jun 24, 2015Nimbostratus
Fantastic, thank you for the replies. I have also got this working by using the clients MDM application to include the UPN as the password field. This is essentially ignored because all users are cert-based auth so the workaround is acceptable to the client. I would still be curious to see your rule 'R Marc' for future reference.
Thanks!
- R_MarcJun 24, 2015NimbostratusIt's not that much different that the stock one, just got rid of the 401 requirement and added more uniqueness to the session cookie. I think the session cookie still should be a little stronger, which I'll add the next time I get a window from the windows folks (they are very risk averse).
when RULE_INIT { set static::actsync_401_http_body "Authentication FailuredError: Authentication Failure" set static::actsync_503_http_body "Service is not availableError: Service is not available" set static::ACCESS_LOG_PREFIX "01490000:7:" } when HTTP_REQUEST { set http_path [string tolower [HTTP::path]] set f_clientless_mode 0 HTTP::header replace X-Teros-Client-IP [IP::client_addr] HTTP::header replace Host mobilemail.mastercard.com if {[SSL::cert count] > 0}{ HTTP::header insert X-Client-Cert [X509::subject [SSL::cert 0]] } if { [HTTP::method] equals "OPTIONS" } { HTTP::respond 200 -version 1.1 noserver Cache-Control "private" Allow "OPTIONS,POST" Server "Microsoft-IIS/8.5" MS-Server-ActiveSync "14.3" MS-ASProtocolVersions "2.0,2.1,2.5,12.0,12.1,14.0,14.1" MS-ASProtocolCommands "Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,Provision,ResolveRecipients,ValidateCert" Public "OPTIONS,POST" X-AspNet-Version "4.0.30319" X-Powered-By: "ASP.NET" X-FEServer "STL3MSXCAS02" Content-Length 0 } if { $http_path == "/microsoft-server-activesync" } { } elseif { $http_path == "/autodiscover/autodiscover.xml" } { set f_auto_discover 1 } else return if { ! [ info exists src_ip ] } { set src_ip [IP::remote_addr] } if { ! [ info exists PROFILE_RESTRICT_SINGLE_IP ] } { set PROFILE_RESTRICT_SINGLE_IP 1 } Only allow HTTP Basic Authentication. set auth_info_b64enc "" set http_hdr_auth [HTTP::header Authorization] regexp -nocase {Basic (.*)} $http_hdr_auth match auth_info_b64enc if { $auth_info_b64enc == "" } { set http_hdr_auth "" } set MRHSession_cookie [HTTP::cookie value MRHSession] Do we have valid MRHSession cookie. if { $MRHSession_cookie != "" } { if { [ACCESS::session exists -state_allow -sid $MRHSession_cookie] } { log -noname accesscontrol.local1.debug "$static::ACCESS_LOG_PREFIX HTTP *VALID* MRHSession cookie: $MRHSession_cookie" Default profile access setting is false if { $PROFILE_RESTRICT_SINGLE_IP == 0 } { return } elseif { [ IP::addr $src_ip equals [ ACCESS::session data get -sid $MRHSession_cookie "session.user.clientip" ] ] } { log -noname accesscontrol.local1.debug "$static::ACCESS_LOG_PREFIX source IP matched" return } else { log -noname accesscontrol.local1.debug "$static::ACCESS_LOG_PREFIX source IP does not matched" } } else { log -noname accesscontrol.local1.debug "$static::ACCESS_LOG_PREFIX HTTP *INVALID* MRHSession cookie: $MRHSession_cookie" } set MRHSession_cookie "" HTTP::cookie remove MRHSession } if { [HTTP::header exists X-Client-Cert] } { set apm_username [ string tolower [HTTP::header X-Client-Cert] ] } else { set apm_username [ string tolower [HTTP::header username] ] } set apm_password [HTTP::password] if { $PROFILE_RESTRICT_SINGLE_IP == 0 } { binary scan [md5 "$apm_password$"] H* user_hash } else { binary scan [md5 "$apm_password$src_ip$apm_username"] H* user_hash } set user_key {} append user_key $apm_username "." $user_hash unset user_hash set f_insert_clientless_mode 0 set apm_cookie_list [ ACCESS::user getsid $user_key ] if { [ llength $apm_cookie_list ] != 0 } { set apm_cookie [ ACCESS::user getkey [ lindex $apm_cookie_list 0 ] ] if { $apm_cookie != "" } { HTTP::cookie insert name MRHSession value $apm_cookie } else { set f_insert_clientless_mode 1 } } else { set f_insert_clientless_mode 1 } if { $f_insert_clientless_mode == 1 } { HTTP::header insert "clientless-mode" 1 HTTP::header insert "username" $apm_username HTTP::header insert "password" $apm_password if { [HTTP::header exists X-Client-Cert] } { log local0. "if: HTTP::header X-Client-Cert: [HTTP::header X-Client-Cert] [IP::client_addr]:[TCP::client_port]" } else { if {[catch {b64decode [lindex [split [HTTP::header Authorization] " "] 1]} authorization] == 0 and $authorization ne ""}{ set username [lindex [split $authorization ":"] 0] log local0. "else: HTTP::header username: $username [IP::client_addr]:[TCP::client_port]" } else { log local0. "failed to decode [lindex [split [HTTP::header Authorization] " "] 1] [IP::client_addr]:[TCP::client_port]" } } } unset f_insert_clientless_mode } when ACCESS_SESSION_STARTED { if { [ info exists user_key ] } { ACCESS::session data set "session.user.uuid" $user_key ACCESS::session data set "session.user.microsoft-exchange-client" 1 ACCESS::session data set "session.user.activesync" 1 if { [ info exists f_auto_discover ] && $f_auto_discover == 1 } { set f_auto_discover 0 ACCESS::session data set "session.user.microsoft-autodiscover" 1 } } } when ACCESS_ACL_ALLOWED { if { [HTTP::header exists X-Client-Cert] } { foreach field [HTTP::header value X-Client-Cert] { if {$field contains "CN="} { set name [string range $field [expr { [string first "=" $field ] + 1} ] end ] HTTP::header remove username HTTP::header replace username $name } } } } when ACCESS_POLICY_COMPLETED { if { ! [ info exists user_key ] } { return } set policy_result [ACCESS::policy result] switch $policy_result { "allow" { } "deny" { ACCESS::respond 401 content $static::actsync_401_http_body Connection close ACCESS::session remove } default { ACCESS::respond 503 content $static::actsync_503_http_body Connection close ACCESS::session remove } } unset user_key } }
- R_MarcJun 24, 2015NimbostratusOh, I forgot, I also added a stock answer for OPTIONS requests. Some Apple devices request options which was causing a failure somewhere (I forget where). I just grabbed what Exhange 2013 returns for an OPTIONS query, and have it statically return that to the user.
- laserJun 25, 2015AltostratusAwesome, I was attempting to workaround the same thing, it was actually the main issue of why my device would fail. Thanks for the follow-up!
- bduncan_11827Feb 23, 2016NimbostratusR Marc, Any chance you can post your updated irule with your last change to this? Any chance you could email it to me? The comment formatting on this site messes up the formatting of the irule you posted. Thanks
- chrisf5az_29935Dec 27, 2016Nimbostratus
I would second posting it in the code block. your one above got all mangled up.