gpst.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2016-2017 Daniel Lenski
  5. *
  6. * Author: Daniel Lenski <dlenski@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * version 2.1, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. */
  17. #include <config.h>
  18. #include "openconnect-internal.h"
  19. #ifdef HAVE_LZ4
  20. #include <lz4.h>
  21. #endif
  22. #include <unistd.h>
  23. #include <fcntl.h>
  24. #include <sys/types.h>
  25. #ifdef _WIN32
  26. #include "win32-ipicmp.h"
  27. #else
  28. #include <sys/wait.h>
  29. /* The BSDs require the first two headers before netinet/ip.h
  30. * (Linux and macOS already #include them within netinet/ip.h)
  31. */
  32. #include <netinet/in_systm.h>
  33. #include <netinet/in.h>
  34. #include <netinet/ip.h>
  35. #include <netinet/ip_icmp.h>
  36. #include <netinet/ip6.h>
  37. #include <netinet/icmp6.h>
  38. #endif
  39. #if defined(__linux__)
  40. /* For TCP_INFO */
  41. # include <linux/tcp.h>
  42. #endif
  43. #include <time.h>
  44. #include <string.h>
  45. #include <ctype.h>
  46. #include <errno.h>
  47. #include <stdlib.h>
  48. #include <stdio.h>
  49. #include <stdarg.h>
  50. /*
  51. * Data packets are encapsulated in the SSL stream as follows:
  52. *
  53. * 0000: Magic "\x1a\x2b\x3c\x4d"
  54. * 0004: Big-endian EtherType (0x0800 for IPv4)
  55. * 0006: Big-endian 16-bit length (not including 16-byte header)
  56. * 0008: Always "\x01\0\0\0\0\0\0\0"
  57. * 0010: data payload
  58. */
  59. /* Strange initialisers here to work around GCC PR#10676 (which was
  60. * fixed in GCC 4.6 but it takes a while for some systems to catch
  61. * up. */
  62. static const struct pkt dpd_pkt = {
  63. .next = NULL,
  64. { .gpst.hdr = { 0x1a, 0x2b, 0x3c, 0x4d } }
  65. };
  66. static int filter_opts(struct oc_text_buf *buf, const char *query, const char *incexc, int include)
  67. {
  68. const char *f, *endf, *eq;
  69. const char *found, *comma;
  70. for (f = query; *f; f=(*endf) ? endf+1 : endf) {
  71. endf = strchrnul(f, '&');
  72. eq = strchr(f, '=');
  73. if (!eq || eq > endf)
  74. eq = endf;
  75. for (found = incexc; *found; found=(*comma) ? comma+1 : comma) {
  76. comma = strchrnul(found, ',');
  77. if (!strncmp(found, f, MAX(comma-found, eq-f)))
  78. break;
  79. }
  80. if ((include && *found) || (!include && !*found)) {
  81. if (buf->pos && buf->data[buf->pos-1] != '?' && buf->data[buf->pos-1] != '&')
  82. buf_append(buf, "&");
  83. buf_append_bytes(buf, f, (int)(endf-f));
  84. }
  85. }
  86. return buf_error(buf);
  87. }
  88. /* Parse this JavaScript-y mess:
  89. "var respStatus = \"Challenge|Error\";\n"
  90. "var respMsg = \"<prompt>\";\n"
  91. "thisForm.inputStr.value = "<inputStr>";\n"
  92. */
  93. static int parse_javascript(char *buf, char **prompt, char **inputStr)
  94. {
  95. const char *start, *end = buf;
  96. int status;
  97. const char *pre_status = "var respStatus = \"",
  98. *pre_prompt = "var respMsg = \"",
  99. *pre_inputStr = "thisForm.inputStr.value = \"";
  100. /* Status */
  101. while (isspace(*end))
  102. end++;
  103. if (strncmp(end, pre_status, strlen(pre_status)))
  104. goto err;
  105. start = end+strlen(pre_status);
  106. end = strchr(start, '\n');
  107. if (!end || end[-1] != ';' || end[-2] != '"')
  108. goto err;
  109. if (!strncmp(start, "Challenge", 8)) status = 0;
  110. else if (!strncmp(start, "Error", 5)) status = 1;
  111. else goto err;
  112. /* Prompt */
  113. while (isspace(*end))
  114. end++;
  115. if (strncmp(end, pre_prompt, strlen(pre_prompt)))
  116. goto err;
  117. start = end+strlen(pre_prompt);
  118. end = strchr(start, '\n');
  119. if (!end || end[-1] != ';' || end[-2] != '"' || (end<start+2))
  120. goto err;
  121. if (prompt)
  122. *prompt = strndup(start, end-start-2);
  123. /* inputStr */
  124. while (isspace(*end))
  125. end++;
  126. if (strncmp(end, pre_inputStr, strlen(pre_inputStr)))
  127. goto err2;
  128. start = end+strlen(pre_inputStr);
  129. end = strchr(start, '\n');
  130. if (!end || end[-1] != ';' || end[-2] != '"' || (end<start+2))
  131. goto err2;
  132. if (inputStr)
  133. *inputStr = strndup(start, end-start-2);
  134. while (isspace(*end))
  135. end++;
  136. if (*end != '\0')
  137. goto err3;
  138. return status;
  139. err3:
  140. if (inputStr) free(*inputStr);
  141. err2:
  142. if (prompt) free(*prompt);
  143. err:
  144. return -EINVAL;
  145. }
  146. int gpst_xml_or_error(struct openconnect_info *vpninfo, char *response,
  147. int (*xml_cb)(struct openconnect_info *, xmlNode *xml_node, void *cb_data),
  148. int (*challenge_cb)(struct openconnect_info *, char *prompt, char *inputStr, void *cb_data),
  149. void *cb_data)
  150. {
  151. xmlDocPtr xml_doc;
  152. xmlNode *xml_node;
  153. char *err = NULL;
  154. char *prompt = NULL, *inputStr = NULL;
  155. int result = -EINVAL;
  156. if (!response) {
  157. vpn_progress(vpninfo, PRG_ERR,
  158. _("Empty response from server\n"));
  159. return -EINVAL;
  160. }
  161. /* is it XML? */
  162. xml_doc = xmlReadMemory(response, strlen(response), "noname.xml", NULL,
  163. XML_PARSE_NOERROR);
  164. if (!xml_doc) {
  165. /* is it Javascript? */
  166. result = parse_javascript(response, &prompt, &inputStr);
  167. switch (result) {
  168. case 1:
  169. vpn_progress(vpninfo, PRG_ERR, _("%s\n"), prompt);
  170. break;
  171. case 0:
  172. vpn_progress(vpninfo, PRG_INFO, _("Challenge: %s\n"), prompt);
  173. result = challenge_cb ? challenge_cb(vpninfo, prompt, inputStr, cb_data) : -EINVAL;
  174. break;
  175. default:
  176. goto bad_xml;
  177. }
  178. free(prompt);
  179. free(inputStr);
  180. goto bad_xml;
  181. }
  182. xml_node = xmlDocGetRootElement(xml_doc);
  183. /* is it <response status="error"><error>..</error></response> ? */
  184. if (xmlnode_is_named(xml_node, "response")
  185. && !xmlnode_match_prop(xml_node, "status", "error")) {
  186. for (xml_node=xml_node->children; xml_node; xml_node=xml_node->next) {
  187. if (!xmlnode_get_val(xml_node, "error", &err))
  188. goto out;
  189. }
  190. goto bad_xml;
  191. }
  192. /* Is it <prelogin-response><status>Error</status><msg>..</msg></prelogin-response> ? */
  193. if (xmlnode_is_named(xml_node, "prelogin-response")) {
  194. char *s = NULL;
  195. int has_err = 0;
  196. xmlNode *x;
  197. for (x=xml_node->children; x; x=x->next) {
  198. if (!xmlnode_get_val(x, "status", &s))
  199. has_err = strcmp(s, "Success");
  200. else
  201. xmlnode_get_val(x, "msg", &err);
  202. }
  203. free(s);
  204. if (has_err)
  205. goto out;
  206. free(err);
  207. err = NULL;
  208. }
  209. /* is it <challenge><user>user.name</user><inputstr>...</inputstr><respmsg>...</respmsg></challenge> */
  210. if (xmlnode_is_named(xml_node, "challenge")) {
  211. for (xml_node=xml_node->children; xml_node; xml_node=xml_node->next) {
  212. xmlnode_get_val(xml_node, "inputstr", &inputStr);
  213. xmlnode_get_val(xml_node, "respmsg", &prompt);
  214. /* XXX: override the username passed to the next form from <user> ? */
  215. }
  216. result = challenge_cb ? challenge_cb(vpninfo, prompt, inputStr, cb_data) : -EINVAL;
  217. free(prompt);
  218. free(inputStr);
  219. goto bad_xml;
  220. }
  221. /* if it's XML, invoke callback (or default to success) */
  222. result = xml_cb ? xml_cb(vpninfo, xml_node, cb_data) : 0;
  223. bad_xml:
  224. if (result == -EINVAL) {
  225. vpn_progress(vpninfo, PRG_ERR,
  226. _("Failed to parse server response\n"));
  227. vpn_progress(vpninfo, PRG_DEBUG,
  228. _("Response was: %s\n"), response);
  229. }
  230. out:
  231. if (err) {
  232. if (!strcmp(err, "GlobalProtect gateway does not exist")
  233. || !strcmp(err, "GlobalProtect portal does not exist")) {
  234. vpn_progress(vpninfo, PRG_DEBUG, "%s\n", err);
  235. result = -EEXIST;
  236. } else if (!strcmp(err, "Invalid authentication cookie") /* equivalent to custom HTTP status 512 */
  237. || !strcmp(err, "Portal name not found") /* cookie is bogus */
  238. || !strcmp(err, "Valid client certificate is required") /* equivalent to custom HTTP status 513 */
  239. || !strcmp(err, "Allow Automatic Restoration of SSL VPN is disabled")) {
  240. /* Any of these errors indicates that retrying won't help us reconnect (EPERM signals this to mainloop.) */
  241. vpn_progress(vpninfo, PRG_ERR, "%s\n", err);
  242. result = -EPERM;
  243. } else {
  244. vpn_progress(vpninfo, PRG_ERR, "%s\n", err);
  245. result = -EINVAL;
  246. }
  247. free(err);
  248. }
  249. if (xml_doc)
  250. xmlFreeDoc(xml_doc);
  251. return result;
  252. }
  253. #define ESP_HEADER_SIZE (4 /* SPI */ + 4 /* sequence number */)
  254. #define ESP_FOOTER_SIZE (1 /* pad length */ + 1 /* next header */)
  255. #ifdef HAVE_ESP
  256. static int check_hmac_algo(struct openconnect_info *v, const char *s)
  257. {
  258. if (!strcmp(s, "sha1")) return HMAC_SHA1;
  259. if (!strcmp(s, "md5")) return HMAC_MD5;
  260. if (!strcmp(s, "sha256")) return HMAC_SHA256;
  261. vpn_progress(v, PRG_ERR, _("Unknown ESP MAC algorithm: %s\n"), s);
  262. return -ENOENT;
  263. }
  264. static int check_enc_algo(struct openconnect_info *v, const char *s)
  265. {
  266. if (!strcmp(s, "aes128") || !strcmp(s, "aes-128-cbc")) return ENC_AES_128_CBC;
  267. if (!strcmp(s, "aes-256-cbc")) return ENC_AES_256_CBC;
  268. vpn_progress(v, PRG_ERR, _("Unknown ESP encryption algorithm: %s\n"), s);
  269. return -ENOENT;
  270. }
  271. /* Reads <KEYTAG/><bits>N</bits><val>hex digits</val></KEYTAG> and saves the
  272. * key in dest, returning its length in bytes.
  273. */
  274. static int xml_to_key(xmlNode *xml_node, unsigned char *dest, int dest_size)
  275. {
  276. int explen = -1, len = 0;
  277. xmlNode *child;
  278. char *p, *s = NULL;
  279. for (child = xml_node->children; child; child=child->next) {
  280. if (xmlnode_get_val(child, "bits", &s) == 0) {
  281. explen = atoi(s);
  282. if (explen & 0x07) goto out;
  283. explen >>= 3;
  284. } else if (xmlnode_get_val(child, "val", &s) == 0) {
  285. for (p=s; p[0] && p[1]; p+=2)
  286. if (len++ < dest_size)
  287. *dest++ = unhex(p);
  288. }
  289. }
  290. out:
  291. free(s);
  292. return (len == explen) ? len : -EINVAL;
  293. }
  294. #endif
  295. /* Return value:
  296. * < 0, on error
  297. * = 0, on success; *form is populated
  298. */
  299. static int gpst_parse_config_xml(struct openconnect_info *vpninfo, xmlNode *xml_node, void *cb_data)
  300. {
  301. xmlNode *member;
  302. int n_dns = 0, esp_keys = 0, esp_v4 = 0, esp_v6 = 0;
  303. int ret = 0;
  304. char *s = NULL;
  305. int ii;
  306. uint32_t esp_magic = 0;
  307. struct in6_addr esp6_magic;
  308. if (!xml_node || !xmlnode_is_named(xml_node, "response"))
  309. return -EINVAL;
  310. struct oc_vpn_option *new_opts = NULL;
  311. struct oc_ip_info new_ip_info = {};
  312. memset(vpninfo->esp_magic, 0, sizeof(vpninfo->esp_magic));
  313. vpninfo->esp_replay_protect = 1;
  314. vpninfo->ssl_times.rekey_method = REKEY_NONE;
  315. /* Parse config */
  316. for (xml_node = xml_node->children; xml_node; xml_node=xml_node->next) {
  317. if (!xmlnode_get_val(xml_node, "ip-address", &s))
  318. new_ip_info.addr = add_option_steal(&new_opts, "ipaddr", &s);
  319. else if (!xmlnode_get_val(xml_node, "ip-address-v6", &s)) {
  320. if (!vpninfo->disable_ipv6)
  321. new_ip_info.addr6 = add_option_steal(&new_opts, "ipaddr6", &s);
  322. } else if (!xmlnode_get_val(xml_node, "netmask", &s)) {
  323. new_ip_info.netmask = add_option_steal(&new_opts, "netmask", &s);
  324. } else if (!xmlnode_get_val(xml_node, "mtu", &s))
  325. new_ip_info.mtu = atoi(s);
  326. else if (!xmlnode_get_val(xml_node, "lifetime", &s))
  327. vpninfo->auth_expiration = time(NULL) + atol(s);
  328. else if (!xmlnode_get_val(xml_node, "quarantine", &s)) {
  329. if (strcmp(s, "no"))
  330. vpn_progress(vpninfo, PRG_DEBUG,
  331. _("WARNING: Config XML contains <quarantine> tag with value of \"%s\".\n"
  332. " VPN connectivity may be disabled or limited.\n"), s);
  333. } else if (!xmlnode_get_val(xml_node, "disconnect-on-idle", &s)) {
  334. int sec = atoi(s);
  335. vpn_progress(vpninfo, PRG_INFO, _("Idle timeout is %d minutes.\n"), sec/60);
  336. vpninfo->idle_timeout = sec;
  337. } else if (!xmlnode_get_val(xml_node, "ssl-tunnel-url", &s)) {
  338. free(vpninfo->urlpath);
  339. vpninfo->urlpath = s;
  340. if (strcmp(s, "/ssl-tunnel-connect.sslvpn"))
  341. vpn_progress(vpninfo, PRG_INFO, _("Non-standard SSL tunnel path: %s\n"), s);
  342. s = NULL;
  343. } else if (!xmlnode_get_val(xml_node, "timeout", &s)) {
  344. int sec = atoi(s);
  345. vpn_progress(vpninfo, PRG_INFO, _("Tunnel timeout (rekey interval) is %d minutes.\n"), sec/60);
  346. vpninfo->ssl_times.last_rekey = time(NULL);
  347. vpninfo->ssl_times.rekey = sec - 60;
  348. vpninfo->ssl_times.rekey_method = REKEY_TUNNEL;
  349. } else if (!xmlnode_get_val(xml_node, "gw-address", &s)) {
  350. /* As remarked in oncp.c, "this is a tunnel; having a
  351. * gateway is meaningless." See esp_send_probes_gp for the
  352. * gory details of what this field actually means.
  353. */
  354. if (vpninfo->peer_addr->sa_family == IPPROTO_IP &&
  355. vpninfo->ip_info.gateway_addr && strcmp(s, vpninfo->ip_info.gateway_addr))
  356. vpn_progress(vpninfo, PRG_DEBUG,
  357. _("Gateway address in config XML (%s) differs from external gateway address (%s).\n"), s, new_ip_info.gateway_addr);
  358. esp_magic = inet_addr(s);
  359. esp_v4 = 1;
  360. } else if (!xmlnode_get_val(xml_node, "gw-address-v6", &s)) {
  361. if (vpninfo->peer_addr->sa_family == IPPROTO_IPV6 &&
  362. vpninfo->ip_info.gateway_addr && strcmp(s, vpninfo->ip_info.gateway_addr))
  363. vpn_progress(vpninfo, PRG_DEBUG,
  364. _("IPv6 gateway address in config XML (%s) differs from external gateway address (%s).\n"), s, vpninfo->ip_info.gateway_addr);
  365. inet_pton(AF_INET6, s, &esp6_magic);
  366. esp_v6 = 1;
  367. } else if (!xmlnode_get_val(xml_node, "connected-gw-ip", &s)) {
  368. if (vpninfo->ip_info.gateway_addr && strcmp(s, vpninfo->ip_info.gateway_addr))
  369. vpn_progress(vpninfo, PRG_DEBUG, _("Config XML <connected-gw-ip> address (%s) differs from external\n"
  370. "gateway address (%s). Please report this to\n"
  371. "<%s>, including any problems\n"
  372. "with ESP or other apparent loss of connectivity or performance.\n"),
  373. s, vpninfo->ip_info.gateway_addr, "openconnect-devel@lists.infradead.org");
  374. } else if (xmlnode_is_named(xml_node, "dns-v6") ||
  375. xmlnode_is_named(xml_node, "dns")) {
  376. for (member = xml_node->children; member && n_dns<3; member=member->next) {
  377. if (!xmlnode_get_val(member, "member", &s)) {
  378. for (ii=0; ii<n_dns; ii++)
  379. /* XX: frequent duplicates between <dns> and <dns-v6> */
  380. if (!strcmp(s, new_ip_info.dns[ii]))
  381. break;
  382. if (ii==n_dns)
  383. new_ip_info.dns[n_dns++] = add_option_steal(&new_opts, "DNS", &s);
  384. }
  385. }
  386. } else if (xmlnode_is_named(xml_node, "wins")) {
  387. for (ii=0, member = xml_node->children; member && ii<3; member=member->next)
  388. if (!xmlnode_get_val(member, "member", &s))
  389. new_ip_info.nbns[ii++] = add_option_steal(&new_opts, "WINS", &s);
  390. } else if (xmlnode_is_named(xml_node, "dns-suffix")) {
  391. struct oc_text_buf *domains = buf_alloc();
  392. for (member = xml_node->children; member; member=member->next)
  393. if (!xmlnode_get_val(member, "member", &s))
  394. buf_append(domains, "%s ", s);
  395. if (buf_error(domains) == 0 && domains->pos > 0) {
  396. domains->data[domains->pos-1] = '\0';
  397. new_ip_info.domain = add_option_steal(&new_opts, "search", &domains->data);
  398. }
  399. buf_free(domains);
  400. } else if (xmlnode_is_named(xml_node, "access-routes-v6") || xmlnode_is_named(xml_node, "exclude-access-routes-v6") ||
  401. xmlnode_is_named(xml_node, "access-routes") || xmlnode_is_named(xml_node, "exclude-access-routes")) {
  402. for (member = xml_node->children; member; member=member->next) {
  403. if (!xmlnode_get_val(member, "member", &s)) {
  404. struct oc_split_include *inc = malloc(sizeof(*inc));
  405. if (!inc) {
  406. ret = -ENOMEM;
  407. goto err;
  408. }
  409. if (xmlnode_is_named(xml_node, "access-routes")) {
  410. inc->route = add_option_steal(&new_opts, "split-include", &s);
  411. inc->next = new_ip_info.split_includes;
  412. new_ip_info.split_includes = inc;
  413. } else {
  414. inc->route = add_option_steal(&new_opts, "split-exclude", &s);
  415. inc->next = new_ip_info.split_excludes;
  416. new_ip_info.split_excludes = inc;
  417. }
  418. }
  419. }
  420. } else if (xmlnode_is_named(xml_node, "ipsec")) {
  421. #ifdef HAVE_ESP
  422. if (vpninfo->dtls_state != DTLS_DISABLED) {
  423. int c = (vpninfo->current_esp_in ^= 1);
  424. struct esp *ei = &vpninfo->esp_in[c], *eo = &vpninfo->esp_out;
  425. vpninfo->old_esp_maxseq = vpninfo->esp_in[c^1].seq + 32;
  426. for (member = xml_node->children; member; member=member->next) {
  427. if (!xmlnode_get_val(member, "udp-port", &s)) udp_sockaddr(vpninfo, atoi(s));
  428. else if (!xmlnode_get_val(member, "enc-algo", &s)) vpninfo->esp_enc = check_enc_algo(vpninfo, s);
  429. else if (!xmlnode_get_val(member, "hmac-algo", &s)) vpninfo->esp_hmac = check_hmac_algo(vpninfo, s);
  430. else if (!xmlnode_get_val(member, "c2s-spi", &s)) eo->spi = htonl(strtoul(s, NULL, 16));
  431. else if (!xmlnode_get_val(member, "s2c-spi", &s)) ei->spi = htonl(strtoul(s, NULL, 16));
  432. else if (xmlnode_is_named(member, "ekey-c2s")) vpninfo->enc_key_len = xml_to_key(member, eo->enc_key, sizeof(eo->enc_key));
  433. else if (xmlnode_is_named(member, "ekey-s2c")) vpninfo->enc_key_len = xml_to_key(member, ei->enc_key, sizeof(ei->enc_key));
  434. else if (xmlnode_is_named(member, "akey-c2s")) vpninfo->hmac_key_len = xml_to_key(member, eo->hmac_key, sizeof(eo->hmac_key));
  435. else if (xmlnode_is_named(member, "akey-s2c")) vpninfo->hmac_key_len = xml_to_key(member, ei->hmac_key, sizeof(ei->hmac_key));
  436. else if (!xmlnode_get_val(member, "ipsec-mode", &s) && strcmp(s, "esp-tunnel"))
  437. vpn_progress(vpninfo, PRG_ERR, _("GlobalProtect config sent ipsec-mode=%s (expected esp-tunnel)\n"), s);
  438. }
  439. if (!(vpninfo->esp_enc > 0 && vpninfo->esp_hmac > 0 && vpninfo->enc_key_len > 0 && vpninfo->hmac_key_len > 0))
  440. vpn_progress(vpninfo, PRG_ERR, "Server's ESP configuration is incomplete or uses unknown algorithms.\n");
  441. else
  442. esp_keys = 1;
  443. }
  444. #else
  445. vpn_progress(vpninfo, PRG_DEBUG, _("Ignoring ESP keys since ESP support not available in this build\n"));
  446. #endif
  447. } else if (xmlnode_is_named(xml_node, "need-tunnel")
  448. || xmlnode_is_named(xml_node, "bw-c2s")
  449. || xmlnode_is_named(xml_node, "bw-s2c")
  450. || xmlnode_is_named(xml_node, "default-gateway")
  451. || xmlnode_is_named(xml_node, "default-gateway-v6")
  452. || xmlnode_is_named(xml_node, "no-direct-access-to-local-network")
  453. || xmlnode_is_named(xml_node, "ip-address-preferred")
  454. || xmlnode_is_named(xml_node, "ip-address-v6-preferred")
  455. || xmlnode_is_named(xml_node, "ipv6-connection")
  456. || xmlnode_is_named(xml_node, "portal")
  457. || xmlnode_is_named(xml_node, "user")) {
  458. /* XX: Do these have any potential value at all for routing configuration or diagnostics? */
  459. } else if (xml_node->type == XML_ELEMENT_NODE) {
  460. free(s);
  461. s = (char *)xmlNodeGetContent(xml_node);
  462. if (strchr((char *)xml_node->name, '6'))
  463. vpn_progress(vpninfo, PRG_ERR, _("Potential IPv6-related GlobalProtect config tag <%s>: %s\n"), xml_node->name, s);
  464. else
  465. vpn_progress(vpninfo, PRG_DEBUG, _("Unknown GlobalProtect config tag <%s>: %s\n"), xml_node->name, s);
  466. }
  467. }
  468. /* Set 10-second DPD/keepalive (same as Windows client) unless
  469. * overridden with --force-dpd */
  470. if (!vpninfo->ssl_times.dpd)
  471. vpninfo->ssl_times.dpd = 10;
  472. vpninfo->ssl_times.keepalive = vpninfo->esp_ssl_fallback = vpninfo->ssl_times.dpd;
  473. /* Warn about IPv6 config, if present, and ESP config, if absent */
  474. if (new_ip_info.addr6)
  475. vpn_progress(vpninfo, PRG_ERR,
  476. _("GlobalProtect IPv6 support is experimental. Please report results to <%s>.\n"),
  477. "openconnect-devel@lists.infradead.org");
  478. #ifdef HAVE_ESP
  479. if (esp_keys && esp_v6 && new_ip_info.addr6) {
  480. /* We got ESP keys, an IPv6 esp_magic address, and an IPv6 address */
  481. vpninfo->esp_magic_af = AF_INET6;
  482. memcpy(vpninfo->esp_magic, &esp6_magic, sizeof(esp6_magic));
  483. setup_esp_keys:
  484. if (openconnect_setup_esp_keys(vpninfo, 0)) {
  485. vpn_progress(vpninfo, PRG_ERR, "Failed to setup ESP keys.\n");
  486. } else {
  487. /* prevent race condition between esp_mainloop() and gpst_mainloop() timers */
  488. vpninfo->dtls_times.last_rekey = time(&vpninfo->new_dtls_started);
  489. vpninfo->delay_tunnel_reason = "awaiting GPST ESP connection";
  490. }
  491. } else if (esp_keys && esp_v4 && new_ip_info.addr) {
  492. /* We got ESP keys, an IPv4 esp_magic address, and an IPv4 address */
  493. vpninfo->esp_magic_af = AF_INET;
  494. memcpy(vpninfo->esp_magic, &esp_magic, sizeof(esp_magic));
  495. goto setup_esp_keys;
  496. } else if (vpninfo->dtls_state != DTLS_DISABLED)
  497. vpn_progress(vpninfo, PRG_ERR,
  498. _("Did not receive ESP keys and matching gateway in GlobalProtect config; tunnel will be TLS only.\n"));
  499. #endif
  500. free(s);
  501. ret = install_vpn_opts(vpninfo, new_opts, &new_ip_info);
  502. if (ret) {
  503. err:
  504. free_optlist(new_opts);
  505. free_split_routes(&new_ip_info);
  506. }
  507. return ret;
  508. }
  509. static int gpst_get_config(struct openconnect_info *vpninfo)
  510. {
  511. char *orig_path;
  512. int result;
  513. struct oc_text_buf *request_body = buf_alloc();
  514. const char *old_addr = vpninfo->ip_info.addr;
  515. const char *old_addr6 = vpninfo->ip_info.addr6;
  516. char *xml_buf = NULL;
  517. /* submit getconfig request */
  518. buf_append(request_body, "client-type=1&protocol-version=p1&internal=no&app-version=5.1.5-8");
  519. append_opt(request_body, "ipv6-support", vpninfo->disable_ipv6 ? "no" : "yes");
  520. append_opt(request_body, "clientos", gpst_os_name(vpninfo));
  521. append_opt(request_body, "os-version", vpninfo->platname);
  522. append_opt(request_body, "hmac-algo", "sha1,md5,sha256");
  523. append_opt(request_body, "enc-algo", "aes-128-cbc,aes-256-cbc");
  524. if (old_addr || old_addr6) {
  525. append_opt(request_body, "preferred-ip", old_addr);
  526. append_opt(request_body, "preferred-ipv6", old_addr6);
  527. filter_opts(request_body, vpninfo->cookie, "preferred-ip,preferred-ipv6", 0);
  528. } else
  529. buf_append(request_body, "&%s", vpninfo->cookie);
  530. if ((result = buf_error(request_body)))
  531. goto out;
  532. orig_path = vpninfo->urlpath;
  533. vpninfo->urlpath = strdup("ssl-vpn/getconfig.esp");
  534. result = do_https_request(vpninfo, "POST", "application/x-www-form-urlencoded", request_body, &xml_buf, NULL, HTTP_NO_FLAGS);
  535. free(vpninfo->urlpath);
  536. vpninfo->urlpath = orig_path;
  537. /* parse getconfig result */
  538. if (result >= 0)
  539. result = gpst_xml_or_error(vpninfo, xml_buf, gpst_parse_config_xml, NULL, NULL);
  540. if (result) {
  541. /* XX: if our "cookie" is bogus (doesn't include at least 'user', 'authcookie',
  542. * and 'portal' fields) the server will respond like this.
  543. */
  544. if (result == -EINVAL && xml_buf && !strcmp(xml_buf, "errors getting SSL/VPN config"))
  545. result = -EPERM;
  546. goto out;
  547. }
  548. if (!vpninfo->ip_info.mtu) {
  549. /* FIXME: GP gateway config always seems to be <mtu>0</mtu> */
  550. char *no_esp_reason = NULL;
  551. #ifdef HAVE_ESP
  552. if (vpninfo->dtls_state == DTLS_DISABLED)
  553. no_esp_reason = _("ESP disabled");
  554. else if (vpninfo->dtls_state == DTLS_NOSECRET)
  555. no_esp_reason = _("No ESP keys received");
  556. #else
  557. no_esp_reason = _("ESP support not available in this build");
  558. #endif
  559. if (!no_esp_reason)
  560. vpninfo->ip_info.mtu = calculate_mtu(
  561. vpninfo, 1,
  562. ESP_HEADER_SIZE + vpninfo->hmac_out_len + MAX_IV_SIZE, /* ESP header size */
  563. ESP_FOOTER_SIZE, /* ESP footer (contributes to payload before padding) */
  564. 16 /* blocksize for both AES-128 and AES-256 */ );
  565. else
  566. vpninfo->ip_info.mtu = calculate_mtu(vpninfo, 0, TLS_OVERHEAD, 0, 1);
  567. vpn_progress(vpninfo, PRG_ERR,
  568. _("No MTU received. Calculated %d for %s%s\n"), vpninfo->ip_info.mtu,
  569. no_esp_reason ? "SSL tunnel. " : "ESP tunnel", no_esp_reason ? : "");
  570. /* return -EINVAL; */
  571. }
  572. out:
  573. buf_free(request_body);
  574. free(xml_buf);
  575. return result;
  576. }
  577. static int gpst_connect(struct openconnect_info *vpninfo)
  578. {
  579. int ret;
  580. struct oc_text_buf *reqbuf;
  581. static const char start_tunnel[12] = "START_TUNNEL"; /* NOT zero-terminated */
  582. char buf[256];
  583. /* We do NOT actually start the HTTPS tunnel if ESP is enabled and we received
  584. * ESP keys, because the ESP keys become invalid as soon as the HTTPS tunnel
  585. * is connected! >:-(
  586. */
  587. if (vpninfo->dtls_state != DTLS_DISABLED && vpninfo->dtls_state != DTLS_NOSECRET)
  588. return 0;
  589. /* Connect to SSL VPN tunnel */
  590. vpn_progress(vpninfo, PRG_DEBUG,
  591. _("Connecting to HTTPS tunnel endpoint ...\n"));
  592. ret = openconnect_open_https(vpninfo);
  593. if (ret)
  594. return ret;
  595. reqbuf = buf_alloc();
  596. buf_append(reqbuf, "GET %s?", vpninfo->urlpath);
  597. filter_opts(reqbuf, vpninfo->cookie, "user,authcookie", 1);
  598. buf_append(reqbuf, " HTTP/1.1\r\n\r\n");
  599. if ((ret = buf_error(reqbuf)))
  600. goto out;
  601. if (vpninfo->dump_http_traffic)
  602. dump_buf(vpninfo, '>', reqbuf->data);
  603. vpninfo->ssl_write(vpninfo, reqbuf->data, reqbuf->pos);
  604. if ((ret = vpninfo->ssl_read(vpninfo, buf, 12)) < 0) {
  605. if (ret == -EINTR)
  606. goto out;
  607. vpn_progress(vpninfo, PRG_ERR,
  608. _("Error fetching GET-tunnel HTTPS response.\n"));
  609. ret = -EINVAL;
  610. goto out;
  611. }
  612. if (!strncmp(buf, start_tunnel, sizeof(start_tunnel))) {
  613. ret = 0;
  614. } else if (ret==0) {
  615. vpn_progress(vpninfo, PRG_ERR,
  616. _("Gateway disconnected immediately after GET-tunnel request.\n"));
  617. ret = -EPIPE;
  618. } else {
  619. if (ret==sizeof(start_tunnel)) {
  620. ret = vpninfo->ssl_gets(vpninfo, buf+sizeof(start_tunnel), sizeof(buf)-sizeof(start_tunnel));
  621. ret = (ret>0 ? ret : 0) + sizeof(start_tunnel);
  622. }
  623. int status = check_http_status(buf, ret);
  624. /* XX: GP servers return 502 when they don't like the cookie */
  625. if (status == 502)
  626. ret = -EPERM;
  627. else {
  628. vpn_progress(vpninfo, PRG_ERR, _("Got unexpected HTTP response: %.*s\n"),
  629. ret, buf);
  630. ret = -EINVAL;
  631. }
  632. }
  633. if (ret < 0)
  634. openconnect_close_https(vpninfo, 0);
  635. else {
  636. monitor_fd_new(vpninfo, ssl);
  637. monitor_read_fd(vpninfo, ssl);
  638. monitor_except_fd(vpninfo, ssl);
  639. vpninfo->ssl_times.last_rx = vpninfo->ssl_times.last_tx = time(NULL);
  640. /* connecting the HTTPS tunnel totally invalidates the ESP keys,
  641. hence shutdown */
  642. if (vpninfo->proto->udp_shutdown)
  643. vpninfo->proto->udp_shutdown(vpninfo);
  644. }
  645. out:
  646. buf_free(reqbuf);
  647. return ret;
  648. }
  649. static int parse_hip_report_check(struct openconnect_info *vpninfo, xmlNode *xml_node, void *cb_data)
  650. {
  651. char *s = NULL;
  652. int result = -EINVAL;
  653. if (!xml_node || !xmlnode_is_named(xml_node, "response"))
  654. goto out;
  655. for (xml_node = xml_node->children; xml_node; xml_node=xml_node->next) {
  656. if (!xmlnode_get_val(xml_node, "hip-report-needed", &s)) {
  657. if (!strcmp(s, "no"))
  658. result = 0;
  659. else if (!strcmp(s, "yes"))
  660. result = -EAGAIN;
  661. else
  662. result = -EINVAL;
  663. goto out;
  664. }
  665. }
  666. out:
  667. free(s);
  668. return result;
  669. }
  670. /* Unlike CSD, the HIP security checker runs during the connection
  671. * phase, not during the authentication phase.
  672. *
  673. * The HIP security checker will (probably) ask us to resubmit the
  674. * HIP report if either of the following changes:
  675. * - Client IP address
  676. * - Client HIP report md5sum
  677. *
  678. * I'm not sure what the md5sum is computed over in the official
  679. * client, but it doesn't really matter.
  680. *
  681. * We just need an identifier for the combination of the local host
  682. * and the VPN gateway which won't change when our IP address
  683. * or authcookie are changed.
  684. */
  685. static int build_csd_token(struct openconnect_info *vpninfo)
  686. {
  687. struct oc_text_buf *buf;
  688. unsigned char md5[16];
  689. int i;
  690. if (vpninfo->csd_token)
  691. return 0;
  692. vpninfo->csd_token = malloc(MD5_SIZE * 2 + 1);
  693. if (!vpninfo->csd_token)
  694. return -ENOMEM;
  695. /* use cookie (excluding volatile authcookie and preferred-ip/ipv6) to build md5sum */
  696. buf = buf_alloc();
  697. filter_opts(buf, vpninfo->cookie, "authcookie,preferred-ip,preferred-ipv6", 0);
  698. if (buf_error(buf))
  699. goto out;
  700. /* save as csd_token */
  701. openconnect_md5(md5, buf->data, buf->pos);
  702. for (i=0; i < MD5_SIZE; i++)
  703. sprintf(&vpninfo->csd_token[i*2], "%02x", md5[i]);
  704. out:
  705. return buf_free(buf);
  706. }
  707. /* check if HIP report is needed (to ssl-vpn/hipreportcheck.esp) or submit HIP report contents (to ssl-vpn/hipreport.esp) */
  708. static int check_or_submit_hip_report(struct openconnect_info *vpninfo, const char *report)
  709. {
  710. int result;
  711. struct oc_text_buf *request_body = buf_alloc();
  712. char *xml_buf=NULL, *orig_path;
  713. /* cookie gives us these fields: authcookie, portal, user, domain, computer, and (maybe the unnecessary) preferred-ip/ipv6 */
  714. buf_append(request_body, "client-role=global-protect-full&%s", vpninfo->cookie);
  715. if (vpninfo->ip_info.addr)
  716. append_opt(request_body, "client-ip", vpninfo->ip_info.addr);
  717. if (vpninfo->ip_info.addr6)
  718. append_opt(request_body, "client-ipv6", vpninfo->ip_info.addr6);
  719. if (report) {
  720. /* XML report contains many characters requiring URL-encoding (%xx) */
  721. buf_ensure_space(request_body, strlen(report)*3);
  722. append_opt(request_body, "report", report);
  723. } else {
  724. result = build_csd_token(vpninfo);
  725. if (result)
  726. goto out;
  727. append_opt(request_body, "md5", vpninfo->csd_token);
  728. }
  729. if ((result = buf_error(request_body)))
  730. goto out;
  731. orig_path = vpninfo->urlpath;
  732. vpninfo->urlpath = strdup(report ? "ssl-vpn/hipreport.esp" : "ssl-vpn/hipreportcheck.esp");
  733. result = do_https_request(vpninfo, "POST", "application/x-www-form-urlencoded", request_body, &xml_buf, NULL, HTTP_NO_FLAGS);
  734. free(vpninfo->urlpath);
  735. vpninfo->urlpath = orig_path;
  736. if (result >= 0)
  737. result = gpst_xml_or_error(vpninfo, xml_buf, report ? NULL : parse_hip_report_check, NULL, NULL);
  738. out:
  739. buf_free(request_body);
  740. free(xml_buf);
  741. return result;
  742. }
  743. static int run_hip_script(struct openconnect_info *vpninfo)
  744. {
  745. #if !defined(_WIN32) && !defined(__native_client__)
  746. int pipefd[2];
  747. int ret;
  748. pid_t child;
  749. #endif
  750. if (!vpninfo->csd_wrapper) {
  751. /* Only warn once */
  752. if (!vpninfo->last_trojan) {
  753. vpn_progress(vpninfo, PRG_ERR,
  754. _("WARNING: Server asked us to submit HIP report with md5sum %s.\n"
  755. " VPN connectivity may be disabled or limited without HIP report submission.\n %s\n"),
  756. vpninfo->csd_token,
  757. #if defined(_WIN32) || defined(__native_client__)
  758. _("However, running the HIP report submission script on this platform is not yet implemented.")
  759. #else
  760. _("You need to provide a --csd-wrapper argument with the HIP report submission script.")
  761. #endif
  762. );
  763. /* XXX: Many GlobalProtect VPNs work fine despite allegedly requiring HIP report submission */
  764. }
  765. return 0;
  766. }
  767. #if defined(_WIN32) || defined(__native_client__)
  768. vpn_progress(vpninfo, PRG_ERR,
  769. _("Error: Running the 'HIP Report' script on this platform is not yet implemented.\n"));
  770. return -EPERM;
  771. #else
  772. vpn_progress(vpninfo, PRG_INFO,
  773. _("Trying to run HIP Trojan script '%s'.\n"),
  774. vpninfo->csd_wrapper);
  775. #ifdef __linux__
  776. if (pipe2(pipefd, O_CLOEXEC))
  777. #endif
  778. {
  779. if (pipe(pipefd)) {
  780. vpn_progress(vpninfo, PRG_ERR, _("Failed to create pipe for HIP script\n"));
  781. return -EPERM;
  782. }
  783. set_fd_cloexec(pipefd[0]);
  784. set_fd_cloexec(pipefd[1]);
  785. }
  786. child = fork();
  787. if (child == -1) {
  788. vpn_progress(vpninfo, PRG_ERR, _("Failed to fork for HIP script\n"));
  789. return -EPERM;
  790. } else if (child > 0) {
  791. /* in parent: read report from child */
  792. struct oc_text_buf *report_buf = buf_alloc();
  793. char b[256];
  794. int i, status;
  795. close(pipefd[1]);
  796. buf_truncate(report_buf);
  797. while ((i = read(pipefd[0], b, sizeof(b))) > 0)
  798. buf_append_bytes(report_buf, b, i);
  799. waitpid(child, &status, 0);
  800. if (!WIFEXITED(status)) {
  801. vpn_progress(vpninfo, PRG_ERR,
  802. _("HIP script '%s' exited abnormally\n"),
  803. vpninfo->csd_wrapper);
  804. ret = -EINVAL;
  805. } else if (WEXITSTATUS(status) != 0) {
  806. vpn_progress(vpninfo, PRG_ERR,
  807. _("HIP script '%s' returned non-zero status: %d\n"),
  808. vpninfo->csd_wrapper, WEXITSTATUS(status));
  809. ret = -EINVAL;
  810. } else {
  811. vpn_progress(vpninfo, PRG_INFO,
  812. _("HIP script '%s' completed successfully (report is %d bytes).\n"),
  813. vpninfo->csd_wrapper, report_buf->pos);
  814. ret = check_or_submit_hip_report(vpninfo, report_buf->data);
  815. if (ret < 0)
  816. vpn_progress(vpninfo, PRG_ERR, _("HIP report submission failed.\n"));
  817. else {
  818. vpn_progress(vpninfo, PRG_INFO, _("HIP report submitted successfully.\n"));
  819. ret = 0;
  820. }
  821. }
  822. buf_free(report_buf);
  823. return ret;
  824. } else {
  825. /* in child: run HIP script */
  826. const char *hip_argv[32];
  827. int i = 0;
  828. close(pipefd[0]);
  829. /* The duplicated fd does not have O_CLOEXEC */
  830. dup2(pipefd[1], 1);
  831. if (set_csd_user(vpninfo) < 0)
  832. exit(1);
  833. hip_argv[i++] = openconnect_utf8_to_legacy(vpninfo, vpninfo->csd_wrapper);
  834. hip_argv[i++] = "--cookie";
  835. hip_argv[i++] = vpninfo->cookie;
  836. if (vpninfo->ip_info.addr) {
  837. hip_argv[i++] = "--client-ip";
  838. hip_argv[i++] = vpninfo->ip_info.addr;
  839. }
  840. if (vpninfo->ip_info.addr6) {
  841. hip_argv[i++] = "--client-ipv6";
  842. hip_argv[i++] = vpninfo->ip_info.addr6;
  843. }
  844. hip_argv[i++] = "--md5";
  845. hip_argv[i++] = vpninfo->csd_token;
  846. hip_argv[i++] = "--client-os";
  847. hip_argv[i++] = gpst_os_name(vpninfo);
  848. hip_argv[i++] = NULL;
  849. execv(hip_argv[0], (char **)hip_argv);
  850. vpn_progress(vpninfo, PRG_ERR,
  851. _("Failed to exec HIP script %s\n"), hip_argv[0]);
  852. exit(1);
  853. }
  854. #endif /* !_WIN32 && !__native_client__ */
  855. }
  856. static int check_and_maybe_submit_hip_report(struct openconnect_info *vpninfo)
  857. {
  858. int ret;
  859. ret = check_or_submit_hip_report(vpninfo, NULL);
  860. if (ret == -EAGAIN) {
  861. vpn_progress(vpninfo, PRG_DEBUG,
  862. _("Gateway says HIP report submission is needed.\n"));
  863. ret = run_hip_script(vpninfo);
  864. } else if (ret == 0)
  865. vpn_progress(vpninfo, PRG_DEBUG,
  866. _("Gateway says no HIP report submission is needed.\n"));
  867. return ret;
  868. }
  869. int gpst_setup(struct openconnect_info *vpninfo)
  870. {
  871. int ret;
  872. /* ESP keys are invalid as soon as we (re-)fetch the configuration, hence shutdown */
  873. if (vpninfo->proto->udp_shutdown)
  874. vpninfo->proto->udp_shutdown(vpninfo);
  875. /* Get configuration */
  876. ret = gpst_get_config(vpninfo);
  877. if (ret)
  878. goto out;
  879. /* Always check HIP after getting configuration */
  880. ret = check_and_maybe_submit_hip_report(vpninfo);
  881. if (ret)
  882. goto out;
  883. /* XX: last_trojan is used both as a sentinel to detect the
  884. * first time we check/submit HIP, and for the mainloop to timeout
  885. * when periodic re-checking is required.
  886. */
  887. vpninfo->last_trojan = time(NULL);
  888. /* Default HIP re-checking to 3600 seconds unless already set by
  889. * --force-trojan or portal config.
  890. */
  891. if (!vpninfo->trojan_interval)
  892. vpninfo->trojan_interval = 3600;
  893. /* Connect tunnel immediately if ESP is not going to be used */
  894. ret = gpst_connect(vpninfo);
  895. out:
  896. return ret;
  897. }
  898. int gpst_mainloop(struct openconnect_info *vpninfo, int *timeout, int readable)
  899. {
  900. int ret;
  901. int work_done = 0;
  902. uint16_t ethertype;
  903. uint32_t one, zero, magic;
  904. /* Starting the HTTPS tunnel kills ESP, so we avoid starting
  905. * it if the ESP tunnel is connected or connecting.
  906. */
  907. switch (vpninfo->dtls_state) {
  908. case DTLS_CONNECTING: /* Can never happen */
  909. case DTLS_CONNECTED:
  910. openconnect_close_https(vpninfo, 0); /* don't keep stale HTTPS socket */
  911. vpn_progress(vpninfo, PRG_INFO,
  912. _("ESP tunnel connected; exiting HTTPS mainloop.\n"));
  913. vpninfo->dtls_state = DTLS_ESTABLISHED;
  914. /* Now that we are connected, let's ensure timeout is less than
  915. * or equal to DTLS DPD/keepalive else we might over sleep, eg
  916. * if timeout is set to DTLS attempt period from ESP mainloop,
  917. * and falsely detect dead peer. */
  918. if (vpninfo->dtls_times.dpd)
  919. if (*timeout > vpninfo->dtls_times.dpd * 1000)
  920. *timeout = vpninfo->dtls_times.dpd * 1000;
  921. /* fall through */
  922. case DTLS_ESTABLISHED:
  923. /* Rekey or check-and-resubmit HIP if needed */
  924. if (keepalive_action(&vpninfo->ssl_times, timeout) == KA_REKEY)
  925. goto do_rekey;
  926. else if (trojan_check_deadline(vpninfo, timeout))
  927. goto do_recheck_hip;
  928. return 0;
  929. case DTLS_SECRET:
  930. case DTLS_SLEEPING:
  931. /* Allow 5 seconds after configuration for ESP to start */
  932. if (!ka_check_deadline(timeout, time(NULL), vpninfo->new_dtls_started + 5)) {
  933. vpninfo->delay_tunnel_reason = "awaiting GPST ESP connection";
  934. return 0;
  935. }
  936. /* ... before we switch to HTTPS instead */
  937. vpn_progress(vpninfo, PRG_ERR,
  938. _("Failed to connect ESP tunnel; using HTTPS instead.\n"));
  939. /* XX: gpst_connect does nothing if ESP is enabled and has secrets */
  940. vpninfo->dtls_state = DTLS_NOSECRET;
  941. if (gpst_connect(vpninfo)) {
  942. vpninfo->quit_reason = "GPST connect failed";
  943. return 1;
  944. }
  945. break;
  946. case DTLS_NOSECRET:
  947. /* HTTPS tunnel already started, or getconfig.esp did not provide any ESP keys */
  948. case DTLS_DISABLED:
  949. /* ESP is disabled */
  950. ;
  951. }
  952. if (vpninfo->ssl_fd == -1)
  953. goto do_reconnect;
  954. while (readable) {
  955. /* Some servers send us packets that are larger than
  956. negotiated MTU. We reserve some extra space to
  957. handle that */
  958. int receive_mtu = MAX(16384, vpninfo->ip_info.mtu);
  959. int len, payload_len;
  960. if (!vpninfo->cstp_pkt) {
  961. vpninfo->cstp_pkt = alloc_pkt(vpninfo, receive_mtu);
  962. if (!vpninfo->cstp_pkt) {
  963. vpn_progress(vpninfo, PRG_ERR, _("Allocation failed\n"));
  964. break;
  965. }
  966. }
  967. len = ssl_nonblock_read(vpninfo, 0, vpninfo->cstp_pkt->gpst.hdr, receive_mtu + 16);
  968. if (!len)
  969. break;
  970. if (len < 0) {
  971. vpn_progress(vpninfo, PRG_ERR, _("Packet receive error: %s\n"), strerror(-len));
  972. goto do_reconnect;
  973. }
  974. if (len < 16) {
  975. vpn_progress(vpninfo, PRG_ERR, _("Short packet received (%d bytes)\n"), len);
  976. vpninfo->quit_reason = "Short packet received";
  977. return 1;
  978. }
  979. /* check packet header */
  980. magic = load_be32(vpninfo->cstp_pkt->gpst.hdr);
  981. ethertype = load_be16(vpninfo->cstp_pkt->gpst.hdr + 4);
  982. payload_len = load_be16(vpninfo->cstp_pkt->gpst.hdr + 6);
  983. one = load_le32(vpninfo->cstp_pkt->gpst.hdr + 8);
  984. zero = load_le32(vpninfo->cstp_pkt->gpst.hdr + 12);
  985. if (magic != 0x1a2b3c4d)
  986. goto unknown_pkt;
  987. if (len != 16 + payload_len) {
  988. vpn_progress(vpninfo, PRG_ERR,
  989. _("Unexpected packet length. SSL_read returned %d (includes 16 header bytes) but header payload_len is %d\n"),
  990. len, payload_len);
  991. dump_buf_hex(vpninfo, PRG_ERR, '<', vpninfo->cstp_pkt->gpst.hdr, 16);
  992. continue;
  993. }
  994. vpninfo->ssl_times.last_rx = time(NULL);
  995. switch (ethertype) {
  996. case 0:
  997. vpn_progress(vpninfo, PRG_DEBUG,
  998. _("Got GPST DPD/keepalive response\n"));
  999. if (one != 0 || zero != 0) {
  1000. vpn_progress(vpninfo, PRG_DEBUG,
  1001. _("Expected 0000000000000000 as last 8 bytes of DPD/keepalive packet header, but got:\n"));
  1002. dump_buf_hex(vpninfo, PRG_DEBUG, '<', vpninfo->cstp_pkt->gpst.hdr + 8, 8);
  1003. }
  1004. continue;
  1005. case 0x0800:
  1006. case 0x86DD:
  1007. vpn_progress(vpninfo, PRG_TRACE,
  1008. _("Received IPv%d data packet of %d bytes\n"),
  1009. ethertype == 0x86DD ? 6 : 4, payload_len);
  1010. if (one != 1 || zero != 0) {
  1011. vpn_progress(vpninfo, PRG_DEBUG,
  1012. _("Expected 0100000000000000 as last 8 bytes of data packet header, but got:\n"));
  1013. dump_buf_hex(vpninfo, PRG_DEBUG, '<', vpninfo->cstp_pkt->gpst.hdr + 8, 8);
  1014. }
  1015. vpninfo->cstp_pkt->len = payload_len;
  1016. queue_packet(&vpninfo->incoming_queue, vpninfo->cstp_pkt);
  1017. vpninfo->cstp_pkt = NULL;
  1018. work_done = 1;
  1019. continue;
  1020. }
  1021. unknown_pkt:
  1022. vpn_progress(vpninfo, PRG_ERR,
  1023. _("Unknown packet. Header dump follows:\n"));
  1024. dump_buf_hex(vpninfo, PRG_ERR, '<', vpninfo->cstp_pkt->gpst.hdr, 16);
  1025. vpninfo->quit_reason = "Unknown packet received";
  1026. return 1;
  1027. }
  1028. /* If SSL_write() fails we are expected to try again. With exactly
  1029. the same data, at exactly the same location. So we keep the
  1030. packet we had before.... */
  1031. if (vpninfo->current_ssl_pkt) {
  1032. handle_outgoing:
  1033. vpninfo->ssl_times.last_tx = time(NULL);
  1034. unmonitor_write_fd(vpninfo, ssl);
  1035. ret = ssl_nonblock_write(vpninfo, 0,
  1036. vpninfo->current_ssl_pkt->gpst.hdr,
  1037. vpninfo->current_ssl_pkt->len + 16);
  1038. if (ret < 0)
  1039. goto do_reconnect;
  1040. else if (!ret) {
  1041. switch (ka_stalled_action(&vpninfo->ssl_times, timeout)) {
  1042. case KA_REKEY:
  1043. goto do_rekey;
  1044. case KA_DPD_DEAD:
  1045. goto peer_dead;
  1046. case KA_NONE:
  1047. return work_done;
  1048. }
  1049. }
  1050. if (ret != vpninfo->current_ssl_pkt->len + 16) {
  1051. vpn_progress(vpninfo, PRG_ERR,
  1052. _("SSL wrote too few bytes! Asked for %d, sent %d\n"),
  1053. vpninfo->current_ssl_pkt->len + 16, ret);
  1054. vpninfo->quit_reason = "Internal error";
  1055. return 1;
  1056. }
  1057. /* Don't free the 'special' packets */
  1058. if (vpninfo->current_ssl_pkt != &dpd_pkt)
  1059. free_pkt(vpninfo, vpninfo->current_ssl_pkt);
  1060. vpninfo->current_ssl_pkt = NULL;
  1061. }
  1062. if (trojan_check_deadline(vpninfo, timeout)) {
  1063. do_recheck_hip:
  1064. vpn_progress(vpninfo, PRG_INFO, _("GlobalProtect HIP check due\n"));
  1065. /* We could just be lazy and treat this as a reconnect, but that
  1066. * would require us to repull the routing configuration and new ESP
  1067. * keys, instead of just redoing the HIP check/submission.
  1068. *
  1069. * Therefore we'll just close the HTTPS tunnel (if up),
  1070. * redo the HIP check/submission, and reconnect the HTTPS tunnel
  1071. * if needed.
  1072. */
  1073. openconnect_close_https(vpninfo, 0);
  1074. ret = check_and_maybe_submit_hip_report(vpninfo);
  1075. if (ret) {
  1076. vpn_progress(vpninfo, PRG_ERR, _("HIP check or report failed\n"));
  1077. vpninfo->quit_reason = "HIP check or report failed";
  1078. return ret;
  1079. }
  1080. /* XX: no need to do_reconnect, since ESP doesn't need reconnection */
  1081. if (gpst_connect(vpninfo))
  1082. vpninfo->quit_reason = "GPST connect failed";
  1083. return 1;
  1084. }
  1085. switch (keepalive_action(&vpninfo->ssl_times, timeout)) {
  1086. case KA_REKEY:
  1087. do_rekey:
  1088. vpn_progress(vpninfo, PRG_INFO, _("GlobalProtect rekey due\n"));
  1089. goto do_reconnect;
  1090. case KA_DPD_DEAD:
  1091. peer_dead:
  1092. vpn_progress(vpninfo, PRG_ERR,
  1093. _("GPST Dead Peer Detection detected dead peer!\n"));
  1094. do_reconnect:
  1095. ret = ssl_reconnect(vpninfo);
  1096. if (ret) {
  1097. vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
  1098. vpninfo->quit_reason = "GPST connect failed";
  1099. return ret;
  1100. }
  1101. if (vpninfo->proto->udp_setup)
  1102. vpninfo->proto->udp_setup(vpninfo);
  1103. return 1;
  1104. case KA_KEEPALIVE:
  1105. /* No need to send an explicit keepalive
  1106. if we have real data to send */
  1107. if (vpninfo->dtls_state != DTLS_ESTABLISHED &&
  1108. vpninfo->outgoing_queue.head)
  1109. break;
  1110. /* fall through */
  1111. case KA_DPD:
  1112. vpn_progress(vpninfo, PRG_DEBUG, _("Send GPST DPD/keepalive request\n"));
  1113. vpninfo->current_ssl_pkt = (struct pkt *)&dpd_pkt;
  1114. goto handle_outgoing;
  1115. }
  1116. /* Service outgoing packet queue */
  1117. while (vpninfo->dtls_state != DTLS_ESTABLISHED &&
  1118. (vpninfo->current_ssl_pkt = dequeue_packet(&vpninfo->outgoing_queue))) {
  1119. struct pkt *this = vpninfo->current_ssl_pkt;
  1120. /* IPv4 or IPv6 EtherType */
  1121. int ethertype = this->len && (this->data[0] & 0xF0) == 0x60 ? 0x86DD : 0x0800;
  1122. /* store header */
  1123. store_be32(this->gpst.hdr, 0x1a2b3c4d);
  1124. store_be16(this->gpst.hdr + 4, ethertype);
  1125. store_be16(this->gpst.hdr + 6, this->len);
  1126. store_le32(this->gpst.hdr + 8, 1);
  1127. store_le32(this->gpst.hdr + 12, 0);
  1128. vpn_progress(vpninfo, PRG_TRACE,
  1129. _("Sending IPv%d data packet of %d bytes\n"),
  1130. (ethertype == 0x86DD ? 6 : 4), this->len);
  1131. goto handle_outgoing;
  1132. }
  1133. /* Work is not done if we just got rid of packets off the queue */
  1134. return work_done;
  1135. }
  1136. int gpst_sso_detect_done(struct openconnect_info *vpninfo,
  1137. const struct oc_webview_result *result)
  1138. {
  1139. int i;
  1140. for (i=0; result->headers != NULL && result->headers[i] != NULL; i+=2) {
  1141. const char *hname = result->headers[i], *hval = result->headers[i+1];
  1142. if (!strcmp(hname, "saml-username")) {
  1143. free(vpninfo->sso_username);
  1144. vpninfo->sso_username = strdup(hval);
  1145. } else if (!strcmp(hname, "prelogin-cookie") ||
  1146. !strcmp(hname, "portal-userauthcookie")) {
  1147. free(vpninfo->sso_token_cookie);
  1148. free(vpninfo->sso_cookie_value);
  1149. vpninfo->sso_token_cookie = strdup(hname);
  1150. vpninfo->sso_cookie_value = strdup(hval);
  1151. }
  1152. }
  1153. if (vpninfo->sso_username && vpninfo->sso_token_cookie && vpninfo->sso_cookie_value) {
  1154. /* Not actually used at the moment, so don't fail if not set by the caller */
  1155. if (result->uri)
  1156. vpninfo->sso_login_final = strdup(result->uri);
  1157. return 0;
  1158. } else
  1159. return -EAGAIN;
  1160. }
  1161. #ifdef HAVE_ESP
  1162. static inline uint32_t csum_partial(uint16_t *buf, int nwords)
  1163. {
  1164. uint32_t sum = 0;
  1165. for(sum=0; nwords>0; nwords--)
  1166. sum += ntohs(*buf++);
  1167. return sum;
  1168. }
  1169. static inline uint16_t csum_finish(uint32_t sum)
  1170. {
  1171. sum = (sum >> 16) + (sum &0xffff);
  1172. sum += (sum >> 16);
  1173. return htons((uint16_t)(~sum));
  1174. }
  1175. static inline uint16_t csum(uint16_t *buf, int nwords)
  1176. {
  1177. return csum_finish(csum_partial(buf, nwords));
  1178. }
  1179. static char magic_ping_payload[16] = "monitor\x00\x00pan ha ";
  1180. int gpst_esp_send_probes(struct openconnect_info *vpninfo)
  1181. {
  1182. /* The GlobalProtect VPN initiates and maintains the ESP connection
  1183. * using specially-crafted ICMP ("ping") packets.
  1184. *
  1185. * 1) These ping packets have a special magic payload. It must
  1186. * include at least the 16 bytes below. The Windows client actually
  1187. * sends this 56-byte version, but the remaining bytes don't
  1188. * seem to matter:
  1189. *
  1190. * "monitor\x00\x00pan ha 0123456789:;<=>? !\"#$%&\'()*+,-./\x10\x11\x12\x13\x14\x15\x16\x17";
  1191. *
  1192. * 2) The ping packets are addressed to the IP supplied in the
  1193. * config XML as <gw-address>. In most cases, this is the
  1194. * same as the *external* IP address of the VPN gateway
  1195. * (vpninfo->ip_info.gateway_addr), but in some cases it is a
  1196. * separate address.
  1197. *
  1198. * Don't blame me. I didn't design this.
  1199. */
  1200. const int icmplen = ICMP_MINLEN + sizeof(magic_ping_payload);
  1201. int plen, seq;
  1202. if (vpninfo->esp_magic_af == AF_INET6)
  1203. plen = sizeof(struct ip6_hdr) + icmplen;
  1204. else
  1205. plen = sizeof(struct ip) + icmplen;
  1206. struct pkt *pkt = alloc_pkt(vpninfo, plen + vpninfo->pkt_trailer);
  1207. if (!pkt)
  1208. return -ENOMEM;
  1209. if (vpninfo->dtls_fd == -1) {
  1210. int fd = udp_connect(vpninfo);
  1211. if (fd < 0) {
  1212. free_pkt(vpninfo, pkt);
  1213. return fd;
  1214. }
  1215. /* We are not connected until we get an ESP packet back */
  1216. vpninfo->dtls_state = DTLS_SLEEPING;
  1217. vpninfo->dtls_fd = fd;
  1218. monitor_fd_new(vpninfo, dtls);
  1219. monitor_read_fd(vpninfo, dtls);
  1220. monitor_except_fd(vpninfo, dtls);
  1221. }
  1222. for (seq=1; seq <= (vpninfo->dtls_state==DTLS_ESTABLISHED ? 1 : 3); seq++) {
  1223. if (vpninfo->esp_magic_af == AF_INET6) {
  1224. memset(pkt, 0, sizeof(*pkt) + plen);
  1225. pkt->len = plen;
  1226. struct ip6_hdr *iph = (void *)pkt->data;
  1227. struct icmp6_hdr *icmph = (void *)(pkt->data + sizeof(*iph));
  1228. /* IPv6 Header */
  1229. iph->ip6_flow = htonl((6 << 28) + /* version 6 */
  1230. (0 << 20) + /* traffic class; match Windows client */
  1231. (0 << 0)); /* flow ID; match Windows client */
  1232. iph->ip6_nxt = IPPROTO_ICMPV6;
  1233. iph->ip6_plen = htons(icmplen);
  1234. iph->ip6_hlim = 128; /* what the Windows client uses */
  1235. inet_pton(AF_INET6, vpninfo->ip_info.addr6, &iph->ip6_src);
  1236. memcpy(&iph->ip6_dst, vpninfo->esp_magic, 16);
  1237. /* ICMPv6 echo request */
  1238. icmph->icmp6_type = ICMP6_ECHO_REQUEST;
  1239. icmph->icmp6_code = 0;
  1240. /* Windows client seemingly uses random IDs here but fall back to
  1241. * 0x4747 even if only to keep Coverity happy about error checking. */
  1242. if (openconnect_random(&icmph->icmp6_data16[0], 2))
  1243. icmph->icmp6_data16[0] = htons(0x4747);
  1244. icmph->icmp6_data16[1] = htons(seq); /* sequence */
  1245. /* required to get gateway to respond */
  1246. memcpy(&icmph[1], magic_ping_payload, sizeof(magic_ping_payload));
  1247. /*
  1248. * IPv6 upper-layer checksums include a pseudo-header
  1249. * for IPv6 which contains the source address, the
  1250. * destination address, the upper-layer packet length
  1251. * and next-header field. See RFC8200 §8.1. The
  1252. * checksum is as follows:
  1253. *
  1254. * checksum 32 bytes of real IPv6 header:
  1255. * src addr (16 bytes)
  1256. * dst addr (16 bytes)
  1257. * 8 bytes more:
  1258. * length of ICMPv6 in bytes (be32)
  1259. * 3 bytes of 0
  1260. * next header byte (IPPROTO_ICMPV6)
  1261. * Then the actual ICMPv6 bytes
  1262. */
  1263. uint32_t sum = csum_partial((uint16_t *)&iph->ip6_src, 8); /* 8 uint16_t */
  1264. sum += csum_partial((uint16_t *)&iph->ip6_dst, 8); /* 8 uint16_t */
  1265. /* The easiest way to checksum the following 8-byte
  1266. * part of the pseudo-header without horridly violating
  1267. * C type aliasing rules is *not* to build it in memory
  1268. * at all. We know the length fits in 16 bits so the
  1269. * partial checksum of 00 00 LL LL 00 00 00 NH ends up
  1270. * being just LLLL + NH.
  1271. */
  1272. sum += IPPROTO_ICMPV6;
  1273. sum += ICMP_MINLEN + sizeof(magic_ping_payload);
  1274. sum += csum_partial((uint16_t *)icmph, icmplen / 2);
  1275. icmph->icmp6_cksum = csum_finish(sum);
  1276. } else {
  1277. memset(pkt, 0, sizeof(*pkt) + plen);
  1278. pkt->len = plen;
  1279. struct ip *iph = (void *)pkt->data;
  1280. struct icmp *icmph = (void *)(pkt->data + sizeof(*iph));
  1281. char *pmagic = (void *)(pkt->data + sizeof(*iph) + ICMP_MINLEN);
  1282. /* IP Header */
  1283. iph->ip_hl = 5;
  1284. iph->ip_v = 4;
  1285. iph->ip_len = htons(sizeof(*iph) + icmplen);
  1286. iph->ip_id = htons(0x4747); /* what the Windows client uses */
  1287. iph->ip_off = htons(IP_DF); /* don't fragment, frag offset = 0 */
  1288. iph->ip_ttl = 64; /* hops */
  1289. iph->ip_p = IPPROTO_ICMP;
  1290. iph->ip_src.s_addr = inet_addr(vpninfo->ip_info.addr);
  1291. memcpy(&iph->ip_dst.s_addr, vpninfo->esp_magic, 4);
  1292. iph->ip_sum = csum((uint16_t *)iph, sizeof(*iph)/2);
  1293. /* ICMP echo request */
  1294. icmph->icmp_type = ICMP_ECHO;
  1295. icmph->icmp_hun.ih_idseq.icd_id = htons(0x4747);
  1296. icmph->icmp_hun.ih_idseq.icd_seq = htons(seq);
  1297. memcpy(pmagic, magic_ping_payload, sizeof(magic_ping_payload)); /* required to get gateway to respond */
  1298. icmph->icmp_cksum = csum((uint16_t *)icmph, (ICMP_MINLEN+sizeof(magic_ping_payload))/2);
  1299. }
  1300. if (vpninfo->dtls_state != DTLS_ESTABLISHED) {
  1301. vpn_progress(vpninfo, PRG_TRACE, _("ICMPv%d probe packet (seq %d) for GlobalProtect ESP:\n"),
  1302. vpninfo->esp_magic_af == AF_INET6 ? 6 : 4, seq);
  1303. dump_buf_hex(vpninfo, PRG_TRACE, '>', pkt->data, pkt->len);
  1304. }
  1305. int pktlen = construct_esp_packet(vpninfo, pkt, vpninfo->esp_magic_af == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IPIP);
  1306. if (pktlen < 0 ||
  1307. send(vpninfo->dtls_fd, (void *)&pkt->esp, pktlen, 0) < 0)
  1308. vpn_progress(vpninfo, PRG_DEBUG, _("Failed to send ESP probe\n"));
  1309. }
  1310. free_pkt(vpninfo, pkt);
  1311. vpninfo->dtls_times.last_tx = time(&vpninfo->new_dtls_started);
  1312. return 0;
  1313. }
  1314. int gpst_esp_catch_probe(struct openconnect_info *vpninfo, struct pkt *pkt)
  1315. {
  1316. if (vpninfo->esp_magic_af == AF_INET6) {
  1317. struct ip6_hdr *iph = (void *)(pkt->data);
  1318. return ( pkt->len >= 41 && (ntohl(iph->ip6_flow) >> 28)==6 /* IPv6 header */
  1319. && iph->ip6_nxt == IPPROTO_ICMPV6 /* IPv6 next header field = ICMPv6 */
  1320. && !memcmp(&iph->ip6_src, vpninfo->esp_magic, 16) /* source == magic address */
  1321. && pkt->len >= 40 + ICMP_MINLEN + sizeof(magic_ping_payload) /* No short-packet segfaults */
  1322. && pkt->data[40]==ICMP6_ECHO_REPLY /* ICMPv6 reply */
  1323. && !memcmp(&pkt->data[40 + ICMP_MINLEN], magic_ping_payload, sizeof(magic_ping_payload)) /* Same magic payload in response */
  1324. );
  1325. } else {
  1326. struct ip *iph = (void *)(pkt->data);
  1327. return ( pkt->len >= 21 && iph->ip_v==4 /* IPv4 header */
  1328. && iph->ip_p==IPPROTO_ICMP /* IPv4 protocol field == ICMP */
  1329. && !memcmp(&iph->ip_src.s_addr, vpninfo->esp_magic, 4) /* source == magic address */
  1330. && pkt->len >= (iph->ip_hl<<2) + ICMP_MINLEN + sizeof(magic_ping_payload) /* No short-packet segfaults */
  1331. && pkt->data[iph->ip_hl<<2]==ICMP_ECHOREPLY /* ICMP reply */
  1332. && !memcmp(&pkt->data[(iph->ip_hl<<2) + ICMP_MINLEN], magic_ping_payload, sizeof(magic_ping_payload)) /* Same magic payload in response */
  1333. );
  1334. }
  1335. }
  1336. #endif /* HAVE_ESP */