/
csd-post.sh
executable file
·153 lines (138 loc) · 4.9 KB
/
csd-post.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/bin/bash
# Cisco Anyconnect CSD wrapper for OpenConnect
#
# Instead of actually downloading and spawning the hostscan trojan,
# this script posts results directly. Ideally we would work out how to
# interpret the DES-encrypted (yay Cisco!) tables.dat and basically
# reimplement the necessary parts hostscan itself. But prepackaged
# answers, tuned to match what the VPN server currently wants to see,
# will work for most people. Of course it's perfectly possible to make
# this tell the truth and not just give prepackaged answers, and most
# people should do that rather than deliberately circumventing their
# server's security policy with lies. This script exists as an example
# to work from.
if ! xmlstarlet --version > /dev/null 2>&1; then
echo "************************************************************************" >&2
echo "WARNING: xmlstarlet not found in path; CSD token extraction may not work" >&2
echo "************************************************************************" >&2
unset XMLSTARLET
else
XMLSTARLET=true
fi
export RESPONSE=$(mktemp /tmp/csdresponseXXXXXXX)
trap 'rm $RESPONSE' EXIT
cat >> $RESPONSE <<EOF
endpoint.os.version="$(uname -s)";
endpoint.os.servicepack="$(uname -r)";
endpoint.os.architecture="$(uname -m)";
endpoint.policy.location="Default";
endpoint.device.protection="none";
endpoint.device.protection_version="3.1.03103";
endpoint.device.hostname="$(hostname)";
endpoint.device.port["9217"]="true";
endpoint.device.port["139"]="true";
endpoint.device.port["53"]="true";
endpoint.device.port["22"]="true";
endpoint.device.port["631"]="true";
endpoint.device.port["445"]="true";
endpoint.device.port["9216"]="true";
endpoint.device.tcp4port["9217"]="true";
endpoint.device.tcp4port["139"]="true";
endpoint.device.tcp4port["53"]="true";
endpoint.device.tcp4port["22"]="true";
endpoint.device.tcp4port["631"]="true";
endpoint.device.tcp4port["445"]="true";
endpoint.device.tcp4port["9216"]="true";
endpoint.device.tcp6port["139"]="true";
endpoint.device.tcp6port["53"]="true";
endpoint.device.tcp6port["22"]="true";
endpoint.device.tcp6port["631"]="true";
endpoint.device.tcp6port["445"]="true";
endpoint.device.MAC["FFFF.FFFF.FFFF"]="true";
endpoint.device.protection_extension="3.6.4900.2";
endpoint.fw["IPTablesFW"]={};
endpoint.fw["IPTablesFW"].exists="true";
endpoint.fw["IPTablesFW"].description="IPTables (Linux)";
endpoint.fw["IPTablesFW"].version="1.6.1";
endpoint.fw["IPTablesFW"].enabled="ok";
EOF
shift
TICKET=
STUB=0
while [ "$1" ]; do
if [ "$1" == "-ticket" ]; then shift; TICKET=${1//\"/}; fi
if [ "$1" == "-stub" ]; then shift; STUB=${1//\"/}; fi
shift
done
PINNEDPUBKEY="-s ${CSD_SHA256:+"-k --pinnedpubkey sha256//$CSD_SHA256"}"
URL="https://$CSD_HOSTNAME/+CSCOE+/sdesktop/token.xml?ticket=$TICKET&stub=$STUB"
if [ -n "$XMLSTARLET" ]; then
TOKEN=$(curl $PINNEDPUBKEY -s "$URL" | xmlstarlet sel -t -v /hostscan/token)
else
TOKEN=$(curl $PINNEDPUBKEY -s "$URL" | sed -n '/<token>/s^.*<token>\(.*\)</token>^\1^p' )
fi
if [ -n "$XMLSTARLET" ]; then
URL="https://$CSD_HOSTNAME/CACHE/sdesktop/data.xml"
curl $PINNEDPUBKEY -s "$URL" | xmlstarlet sel -t -v '/data/hostscan/field/@value' | while read -r ENTRY; do
# XX: How are ' and , characters escaped in this?
TYPE="$(sed "s/^'\(.*\)','\(.*\)','\(.*\)'$/\1/" <<< "$ENTRY")"
NAME="$(sed "s/^'\(.*\)','\(.*\)','\(.*\)'$/\2/" <<< "$ENTRY")"
VALUE="$(sed "s/^'\(.*\)','\(.*\)','\(.*\)'$/\3/" <<< "$ENTRY")"
if [ "$TYPE" != "$ENTRY" ]; then
case "$TYPE" in
File)
BASENAME="$(basename "$VALUE")"
cat >> $RESPONSE <<EOF
endpoint.file["$NAME"]={};
endpoint.file["$NAME"].path="$VALUE";
endpoint.file["$NAME"].name="$BASENAME";
EOF
TS=$(stat -c %Y "$VALUE" 2>/dev/null)
if [ "$TS" = "" ]; then
cat >> $RESPONSE <<EOF
endpoint.file["$NAME"].exists="false";
EOF
else
LASTMOD=$(( $(date +%s) - $TS ))
cat >> $RESPONSE <<EOF
endpoint.file["$NAME"].exists="true";
endpoint.file["$NAME"].lastmodified="$LASTMOD";
endpoint.file["$NAME"].timestamp="$TS";
EOF
CRC32=$(crc32 "$VALUE")
if [ "$CRC32" != "" ]; then
cat >> $RESPONSE <<EOF
endpoint.file["$NAME"].crc32="0x$CRC32";
EOF
fi
fi
;;
Process)
if pidof "$VALUE" 2> /dev/null; then
EXISTS=true
else
EXISTS=false
fi
cat >> $RESPONSE <<EOF
endpoint.process["$NAME"]={};
endpoint.process["$NAME"].name="$VALUE";
endpoint.process["$NAME"].exists="$EXISTS";
EOF
## XX: Add '.path' if it's running?
;;
Registry)
# We silently ignore registry entry requests
;;
*)
echo "Unhandled hostscan element of type '$TYPE': '$NAME'/'$VALUE'"
;;
esac
else
echo "Unhandled hostscan field '$ENTRY'"
fi
done
fi
COOKIE_HEADER="Cookie: sdesktop=$TOKEN"
CONTENT_HEADER="Content-Type: text/xml"
URL="https://$CSD_HOSTNAME/+CSCOE+/sdesktop/scan.xml?reusebrowser=1"
curl $PINNEDPUBKEY -v -H "$CONTENT_HEADER" -H "$COOKIE_HEADER" --data @$RESPONSE "$URL"