SHARE
TWEET

F5 - APM ga_code_verify

a guest Jan 8th, 2018 24 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. when ACCESS_POLICY_AGENT_EVENT {
  2.  
  3.     if { [ACCESS::policy agent_id] eq "ga_code_verify" } {
  4.         ### Google Authenticator verification settings ###
  5.  
  6.         # lock the user out after x attempts for a period of x seconds
  7.         set static::lockout_attempts 3
  8.         set static::lockout_period 30
  9.  
  10.         # logon page session variable name for code attempt form field
  11.         set static::ga_code_form_field "ga_code_attempt"
  12.  
  13.         # key (shared secret) storage method: ldap, ad, or datagroup
  14.         set static::ga_key_storage "datagroup"
  15.  
  16.         # LDAP attribute for key if storing in LDAP (optional)
  17.         set static::ga_key_ldap_attr "google_auth_key"
  18.  
  19.         # Active Directory attribute for key if storing in AD (optional)
  20.         set static::ga_key_ad_attr "google_auth_key"
  21.  
  22.         # datagroup name if storing key in a datagroup (optional)
  23.         set static::ga_key_dg "google_auth_keys"
  24.  
  25.  
  26.         #####################################
  27.         ### DO NOT MODIFY BELOW THIS LINE ###
  28.         #####################################
  29.  
  30.         # set lockout table
  31.         set static::lockout_state_table "[virtual name]_lockout_status"
  32.  
  33.         # set variables from APM logon page
  34.         set username [ACCESS::session data get session.logon.last.username]
  35.         set ga_code_attempt [ACCESS::session data get session.logon.last.$static::ga_code_form_field]
  36.  
  37.         # retrieve key from specified storage
  38.         set ga_key ""
  39.  
  40.         switch $static::ga_key_storage {
  41.             ldap {
  42.                 set ga_key [ACCESS::session data get session.ldap.last.attr.$static::ga_key_ldap_attr]
  43.             }
  44.             ad {
  45.                 set ga_key [ACCESS::session data get session.ad.last.attr.$static::ga_key_ad_attr]
  46.             }
  47.             datagroup {
  48.                 set ga_key [class lookup $username $static::ga_key_dg]
  49.             }
  50.         }
  51.  
  52.         # increment the number of login attempts for the user
  53.         set prev_attempts [table incr -notouch -subtable $static::lockout_state_table $username]
  54.         table timeout -subtable $static::lockout_state_table $username $static::lockout_period
  55.  
  56.         # verification result value:
  57.         # 0 = successful
  58.         # 1 = failed
  59.         # 2 = no key found
  60.         # 3 = invalid key length
  61.         # 4 = user locked out
  62.  
  63.         # make sure that the user isn't locked out before calculating GA code
  64.         if { $prev_attempts <= $static::lockout_attempts } {
  65.  
  66.             # check that a valid key was retrieved, then proceed
  67.             if { [string length $ga_key] == 16 } {
  68.                 # begin - Base32 decode to binary
  69.  
  70.                 # Base32 alphabet (see RFC 4648)
  71.                 array set static::b32_alphabet {
  72.                     A 0  B 1  C 2  D 3
  73.                     E 4  F 5  G 6  H 7
  74.                     I 8  J 9  K 10 L 11
  75.                     M 12 N 13 O 14 P 15
  76.                     Q 16 R 17 S 18 T 19
  77.                     U 20 V 21 W 22 X 23
  78.                     Y 24 Z 25 2 26 3 27
  79.                     4 28 5 29 6 30 7 31
  80.                 }
  81.  
  82.                 set ga_key [string toupper $ga_key]
  83.                 set l [string length $ga_key]
  84.                 set n 0
  85.                 set j 0
  86.                 set ga_key_bin ""
  87.  
  88.                 for { set i 0 } { $i < $l } { incr i } {
  89.                     set n [expr $n << 5]
  90.                     set n [expr $n + $static::b32_alphabet([string index $ga_key $i])]
  91.                     set j [incr j 5]
  92.  
  93.                     if { $j >= 8 } {
  94.                         set j [incr j -8]
  95.                         append ga_key_bin [format %c [expr ($n & (0xFF << $j)) >> $j]]
  96.                     }
  97.                 }
  98.  
  99.                 # end - Base32 decode to binary
  100.  
  101.                 # begin - HMAC-SHA1 calculation of Google Auth token
  102.  
  103.                 set time [binary format W* [expr [clock seconds] / 30]]
  104.  
  105.                 set ipad ""
  106.                 set opad ""
  107.  
  108.                 for { set j 0 } { $j < [string length $ga_key_bin] } { incr j } {
  109.                     binary scan $ga_key_bin @${j}H2 k
  110.                     set o [expr 0x$k ^ 0x5C]
  111.                     set i [expr 0x$k ^ 0x36]
  112.                     append ipad [format %c $i]
  113.                     append opad [format %c $o]
  114.                 }
  115.  
  116.                 while { $j < 64 } {
  117.                     append ipad 6
  118.                     append opad \\
  119.                     incr j
  120.                 }
  121.  
  122.                 binary scan [sha1 $opad[sha1 ${ipad}${time}]] H* token
  123.  
  124.                 # end - HMAC-SHA1 calculation of Google Auth hex token
  125.  
  126.                 # begin - extract code from Google Auth hex token
  127.  
  128.                 set offset [expr ([scan [string index $token end] %x] & 0x0F) << 1]
  129.                 set ga_code [expr (0x[string range $token $offset [expr $offset + 7]] & 0x7FFFFFFF) % 1000000]
  130.                 set ga_code [format %06d $ga_code]
  131.  
  132.                 # end - extract code from Google Auth hex token
  133.  
  134.                 if { $ga_code_attempt eq $ga_code } {
  135.                     # code verification successful
  136.                     set ga_result 0
  137.                 } else {
  138.                     # code verification failed
  139.                     set ga_result 1
  140.                 }
  141.             } elseif { [string length $ga_key] > 0 } {
  142.                 # invalid key length, greater than 0, but not length not equal to 16 chars
  143.                 set ga_result 3
  144.             } else {
  145.                 # could not retrieve user's key
  146.                 set ga_result 2
  147.             }
  148.         } else {
  149.             # user locked out due to too many failed attempts
  150.             set ga_result 4
  151.         }
  152.  
  153.         # set code verification result in session variable
  154.         ACCESS::session data set session.custom.ga_result $ga_result
  155.     }
  156. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top