TCL procedures for Base32 encoding/decoding
Problem this snippet solves: Hi Folks, the iRule below contains two TCL procedures to support Base32 encoding and decoding (see RFC 4648 as well as RFC 3548) within iRules. The procedures are based on a rather simple but extensive [string map] syntax to translate or untranslate the Base32 alphabet on a given input data stream via its binary string representation. Compared to other Base32 libraries, which may convert the input on a per-charater/quantum basis, the single step [string map] translation will require significant less CPU cycles to handle the base32 encodings / decodings. Note: The provided Base32 decoder uses a liberal input validation (see RFC 4648 Section 3.3), by ignoring incorrect "=" paddings, accepting upper as well as lower case base32 alphabet characters, automatically translating "0" (zero) to "O", "1" (one) to "I", "8" (eight) to "B" and silently removing any WHITESPACE, TAB and "CRLF" sequences from the input. If the input string contains any other non-Base32 alphabet characters, an internal error will be raised and the output will become an empty string. Cheers, Kai How to use this snippet: The iRule below contains a RULE_INIT event which outlines the procedure usage. Enjoy! Code : when RULE_INIT { set string "Hello World!" set output [call b32encode $string] log local0.debug "Base32 encoded the input \"$string\" to \"$output\"" set string "JBSWY3DPEBLW64TMMQQQ====" set output [call b32decode $string] log local0.debug "Base32 decoded the input \"$string\" to \"$output\"" } proc b32decode { input } { set bin [string map -nocase [list A 00000 B 00001 C 00010 D 00011 \ E 00100 F 00101 G 00110 H 00111 \ I 01000 J 01001 K 01010 L 01011 \ M 01100 N 01101 O 01110 P 01111 \ Q 10000 R 10001 S 10010 T 10011 \ U 10100 V 10101 W 10110 X 10111 \ Y 11000 Z 11001 2 11010 3 11011 \ 4 11100 5 11101 6 11110 7 11111 \ = "" 0 01110 1 01000 8 00001 \ " " "" "" "" "\n" ""] $input] if { [catch { set output [binary format B[expr { int( [string length $bin] / 8 ) * 8 }] $bin] }] } then { set output "" } return $output } proc b32encode { input } { binary scan $input B* bin return [string map [list 00000 A 00001 B 00010 C 00011 D \ 00100 E 00101 F 00110 G 00111 H \ 01000 I 01001 J 01010 K 01011 L \ 01100 M 01101 N 01110 O 01111 P \ 10000 Q 10001 R 10010 S 10011 T \ 10100 U 10101 V 10110 W 10111 X \ 11000 Y 11001 Z 11010 2 11011 3 \ 11100 4 11101 5 11110 6 11111 7 \ 0000 A=== 0001 C=== 0010 E=== 0011 G=== \ 0100 I=== 0101 K=== 0110 M=== 0111 O=== \ 1000 Q=== 1001 S=== 1010 U=== 1011 W=== \ 1100 Y=== 1101 2=== 1110 4=== 1111 6=== \ 000 A====== 001 E====== 010 I====== 011 M====== \ 100 Q====== 101 U====== 110 Y====== 111 4====== \ 00 A= 01 I= 10 Q= 11 Y= \ 0 A==== 1 Q==== ] $bin] } Tested this on version: 12.0697Views0likes0CommentsSanitize special characters in AD groups names
Problem this snippet solves: With APM, when you query Active Directory to retrieve the groups membership, if an AD group contains one or several special characters, the name of the group is considered not printable by APM and therefore is transformed in hex format. For example, if the name of an AD group is "Comptes_éditeurs" (in french), the APM session variable after AD query will be "session.ad.last.attr.memberOf = 0x436f6d707465735fc3a964697465757273". This is not convenient for usage in the APM policy. This snippet offers an iRule to transform "not printable" group names into printable group names by replacing all not printable chars by printable ones. Indeed, the previous example "Comptes_éditeurs" will be transformed by this snippet into "Comptes_editeurs", which will be printed properly and can be used as usual in an APM policy. How to use this snippet: Installation irule To make it works, you need to install the irule on the Virtual Server that publish your application with APM authentication. datagroup You need to create a strings datagroup named "dg_special_chars" that contains all the not printable chars you want to replace with their replacement char. The following datagroup will replace "é, è, ê, ë" with the normal "e" : c3a8 : 65 (è => e) c3a9 : 65 (é => e) c3aa : 65 (ê => e) c3ab : 65 (ë => e) The original special chars here (keys in the datagroup) are in hex format of UTF-8. You can have a look here http://www.utf8-chartable.de/ to find them. The replacement chars (values in the datagroup) are in hex format of standard ASCII. You can have a look here in the "ASCII printable characters" table http://www.rapidtables.com/code/text/ascii-table.htm. For example, if you need to replace "£" with "?", you need the following entry in your datagroup : c2a3 : 3f APM Policy In your APM policy you need to add a bloc "iRule Event" right after you call AD Query and before you test groups membership. In the "iRule Event" bloc, the "Custom iRule Event Agent" needs to be "clean_group_names". After this iRule Event, the sanitized groups names will be stored in the APM session variable "session.custom.ad.memberOf". To test groups membership, you can use the following condition in an "Empty" bloc : expr { [mcget {session.custom.ad.memberOf}] contains "CN=MY_GROUP, CN=Users, DC=MY_DOMAIN" } Code : when ACCESS_POLICY_AGENT_EVENT { if { [ACCESS::policy agent_id] eq "clean_group_names" } { set newMemberOf " | " set memberOf [ACCESS::session data get "session.ad.last.attr.memberOf"] set splited [split $memberOf "|"] # Loop through all groups foreach field $splited { # If the group starts with 0x, it is hexa, needs to be decoded if { $field starts_with " 0x" } { # remove spaces set trimed [string trim $field " "] # skip the 0x at the beginning set hex_data [string tolower [substr $trimed 2]] # Loop through all items in datagroup foreach item [class names dg_special_chars] { set new_char [class lookup $item dg_special_chars] # Replace the special char with a "normal" char regsub -all $item $hex_data $new_char hex_data } # Decode the hexa without special chars to string set groupStr [binary format H* $hex_data] # Concat the sanitize group name to the list set newMemberOf [concat $newMemberOf $groupStr " | "] # The group is not hexa, just concat the value as it is } elseif { $field ne "" } { set newMemberOf [concat $newMemberOf $field " | "] } } # Store the sanitize memberOf into a new session var ACCESS::session data set "session.custom.ad.memberOf" $newMemberOf } } Tested this on version: 12.11.2KViews0likes4Comments