http.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2008-2015 Intel Corporation.
  5. * Copyright © 2008 Nick Andrew <nick@nick-andrew.net>
  6. *
  7. * Author: David Woodhouse <dwmw2@infradead.org>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public License
  11. * version 2.1, as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. */
  18. #include <config.h>
  19. #include "openconnect-internal.h"
  20. #include <libxml/uri.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. #include <time.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include <errno.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <stdarg.h>
  30. static int proxy_write(struct openconnect_info *vpninfo, char *buf, size_t len);
  31. static int proxy_read(struct openconnect_info *vpninfo, char *buf, size_t len);
  32. /*
  33. * We didn't really want to have to do this for ourselves -- one might have
  34. * thought that it would be available in a library somewhere. But neither
  35. * cURL nor Neon have reliable cross-platform ways of either using a cert
  36. * from the TPM, or just reading from / writing to a transport which is
  37. * provided by their caller.
  38. */
  39. int http_add_cookie(struct openconnect_info *vpninfo, const char *option,
  40. const char *value, int replace)
  41. {
  42. struct oc_vpn_option *new, **this;
  43. if (*value) {
  44. new = malloc(sizeof(*new));
  45. if (!new) {
  46. vpn_progress(vpninfo, PRG_ERR,
  47. _("No memory for allocating cookies\n"));
  48. return -ENOMEM;
  49. }
  50. new->next = NULL;
  51. new->option = strdup(option);
  52. new->value = strdup(value);
  53. if (!new->option || !new->value) {
  54. free(new->option);
  55. free(new->value);
  56. free(new);
  57. return -ENOMEM;
  58. }
  59. } else {
  60. /* Kill cookie; don't replace it */
  61. new = NULL;
  62. /* This would be meaningless */
  63. if (!replace)
  64. return -EINVAL;
  65. }
  66. for (this = &vpninfo->cookies; *this; this = &(*this)->next) {
  67. if (!strcmp(option, (*this)->option)) {
  68. if (!replace) {
  69. free(new->value);
  70. free(new->option);
  71. free(new);
  72. return 0;
  73. }
  74. /* Replace existing cookie */
  75. if (new)
  76. new->next = (*this)->next;
  77. else
  78. new = (*this)->next;
  79. free((*this)->option);
  80. free((*this)->value);
  81. free(*this);
  82. *this = new;
  83. break;
  84. }
  85. }
  86. if (new && !*this) {
  87. *this = new;
  88. new->next = NULL;
  89. }
  90. return 0;
  91. }
  92. const char *http_get_cookie(struct openconnect_info *vpninfo, const char *name)
  93. {
  94. struct oc_vpn_option *this;
  95. for (this = vpninfo->cookies; this; this = this->next) {
  96. if (!strcmp(this->option, name))
  97. return this->value;
  98. }
  99. return NULL;
  100. }
  101. /* Some protocols use an "authentication cookie" which needs
  102. * to be split into multiple HTTP cookies. (For example, oNCP
  103. * 'DSSignInUrl=/; DSID=xxx; DSFirstAccess=xxx; DSLastAccess=xxx')
  104. * Process those into vpninfo->cookies.
  105. */
  106. int internal_split_cookies(struct openconnect_info *vpninfo, int replace, const char *def_cookie)
  107. {
  108. char *p = vpninfo->cookie;
  109. while (p && *p) {
  110. char *semicolon = strchr(p, ';');
  111. char *equals;
  112. if (semicolon)
  113. *semicolon = 0;
  114. equals = strchr(p, '=');
  115. if (equals) {
  116. *equals = 0;
  117. http_add_cookie(vpninfo, p, equals+1, replace);
  118. *equals = '=';
  119. } else if (def_cookie) {
  120. /* XX: assume this represents a single cookie's value */
  121. http_add_cookie(vpninfo, def_cookie, p, replace);
  122. } else {
  123. vpn_progress(vpninfo, PRG_ERR, _("Invalid cookie '%s'\n"), p);
  124. return -EINVAL;
  125. }
  126. p = semicolon;
  127. if (p) {
  128. *p = ';';
  129. p++;
  130. while (*p && isspace((int)(unsigned char)*p))
  131. p++;
  132. }
  133. }
  134. return 0;
  135. }
  136. int urldecode_inplace(char *p)
  137. {
  138. char *q;
  139. if (!p)
  140. return -EINVAL;
  141. for (q = p; *p; p++, q++) {
  142. if (*p == '+') {
  143. *q = ' ';
  144. } else if (*p == '%' && isxdigit((int)(unsigned char)p[1]) &&
  145. isxdigit((int)(unsigned char)p[2])) {
  146. *q = unhex(p + 1);
  147. p += 2;
  148. } else
  149. *q = *p;
  150. }
  151. *q = 0;
  152. return 0;
  153. }
  154. /* Read one HTTP header line into hdrbuf, potentially allowing for
  155. * continuation lines. Will never leave a character in 'nextchar' when
  156. * an empty line (signifying end of headers) is received. Will only
  157. * return success when hdrbuf is valid. */
  158. static int read_http_header(struct openconnect_info *vpninfo, char *nextchar,
  159. struct oc_text_buf *hdrbuf, int allow_cont)
  160. {
  161. int eol = 0;
  162. int ret;
  163. char c;
  164. buf_truncate(hdrbuf);
  165. c = *nextchar;
  166. if (c) {
  167. *nextchar = 0;
  168. goto skip_first;
  169. }
  170. while (1) {
  171. ret = vpninfo->ssl_read(vpninfo, &c, 1);
  172. if (ret < 0)
  173. return ret;
  174. if (ret != 1)
  175. return -EINVAL;
  176. /* If we were looking for a continuation line and didn't get it,
  177. * stash the character we *did* get into *nextchar for next time. */
  178. if (eol && c != ' ' && c != '\t') {
  179. *nextchar = c;
  180. return buf_error(hdrbuf);
  181. }
  182. eol = 0;
  183. skip_first:
  184. if (c == '\n') {
  185. if (!buf_error(hdrbuf) && hdrbuf->pos &&
  186. hdrbuf->data[hdrbuf->pos - 1] == '\r') {
  187. hdrbuf->pos--;
  188. hdrbuf->data[hdrbuf->pos] = 0;
  189. }
  190. /* For a non-empty header line, see if there's a continuation */
  191. if (allow_cont && hdrbuf->pos) {
  192. eol = 1;
  193. continue;
  194. }
  195. return buf_error(hdrbuf);
  196. }
  197. buf_append_bytes(hdrbuf, &c, 1);
  198. }
  199. return buf_error(hdrbuf);
  200. }
  201. #define BODY_HTTP10 -1
  202. #define BODY_CHUNKED -2
  203. int process_http_response(struct openconnect_info *vpninfo, int connect,
  204. int (*header_cb)(struct openconnect_info *, char *, char *),
  205. struct oc_text_buf *body)
  206. {
  207. struct oc_text_buf *hdrbuf = buf_alloc();
  208. char nextchar = 0;
  209. int bodylen = BODY_HTTP10;
  210. int closeconn = 0;
  211. int result;
  212. int ret = -EINVAL;
  213. int i;
  214. buf_truncate(body);
  215. /* Ensure it has *something* in it, so that we can dereference hdrbuf->data
  216. * later without checking (for anything except buf_error(hdrbuf), which is
  217. * what read_http_header() uses for its return code anyway). */
  218. buf_append_bytes(hdrbuf, "\0", 1);
  219. cont:
  220. ret = read_http_header(vpninfo, &nextchar, hdrbuf, 0);
  221. if (ret) {
  222. vpn_progress(vpninfo, PRG_ERR, _("Error reading HTTP response: %s\n"),
  223. strerror(-ret));
  224. goto err;
  225. }
  226. if (!strncmp(hdrbuf->data, "HTTP/1.0 ", 9))
  227. closeconn = 1;
  228. if ((!closeconn && strncmp(hdrbuf->data, "HTTP/1.1 ", 9)) ||
  229. !(result = atoi(hdrbuf->data + 9))) {
  230. vpn_progress(vpninfo, PRG_ERR,
  231. _("Failed to parse HTTP response '%s'\n"), hdrbuf->data);
  232. ret = -EINVAL;
  233. goto err;
  234. }
  235. vpn_progress(vpninfo, (result == 200 || result == 407) ? PRG_DEBUG : PRG_INFO,
  236. _("Got HTTP response: %s\n"), hdrbuf->data);
  237. /* Eat headers... */
  238. while (1) {
  239. char *colon;
  240. char *hdrline;
  241. ret = read_http_header(vpninfo, &nextchar, hdrbuf, 1);
  242. if (ret) {
  243. vpn_progress(vpninfo, PRG_ERR, _("Error reading HTTP response: %s\n"),
  244. strerror(-ret));
  245. goto err;
  246. }
  247. /* Empty line ends headers */
  248. if (!hdrbuf->pos)
  249. break;
  250. hdrline = hdrbuf->data;
  251. colon = strchr(hdrline, ':');
  252. if (!colon) {
  253. vpn_progress(vpninfo, PRG_ERR,
  254. _("Ignoring unknown HTTP response line '%s'\n"), hdrline);
  255. continue;
  256. }
  257. *(colon++) = 0;
  258. if (*colon == ' ')
  259. colon++;
  260. /* Handle Set-Cookie first so that we can avoid printing the
  261. webvpn cookie in the verbose debug output */
  262. if (!strcasecmp(hdrline, "Set-Cookie")) {
  263. char *semicolon = strchr(colon, ';');
  264. const char *print_equals;
  265. char *equals = strchr(colon, '=');
  266. if (semicolon)
  267. *semicolon = 0;
  268. if (!equals) {
  269. vpn_progress(vpninfo, PRG_ERR,
  270. _("Invalid cookie offered: %s\n"), hdrline);
  271. ret = -EINVAL;
  272. goto err;
  273. }
  274. *(equals++) = 0;
  275. print_equals = equals;
  276. /* Don't print the webvpn cookie unless it's empty; we don't
  277. want people posting it in public with debugging output */
  278. if (vpninfo->proto->secure_cookie && !strcmp(colon, vpninfo->proto->secure_cookie) && *equals)
  279. print_equals = _("<elided>");
  280. vpn_progress(vpninfo, PRG_DEBUG, "%s: %s=%s%s%s\n",
  281. hdrline, colon, print_equals, semicolon ? ";" : "",
  282. semicolon ? (semicolon+1) : "");
  283. /* The server tends to ask for the username and password as
  284. usual, even if we've already failed because it didn't like
  285. our cert. Thankfully it does give us this hint... */
  286. if (!strcmp(colon, "ClientCertAuthFailed"))
  287. vpn_progress(vpninfo, PRG_ERR,
  288. _("SSL certificate authentication failed\n"));
  289. ret = http_add_cookie(vpninfo, colon, equals, 1);
  290. if (ret)
  291. goto err;
  292. } else {
  293. vpn_progress(vpninfo, PRG_DEBUG, "%s: %s\n", hdrline, colon);
  294. }
  295. if (!strcasecmp(hdrline, "Connection")) {
  296. if (!strcasecmp(colon, "Close"))
  297. closeconn = 1;
  298. #if 0
  299. /* This might seem reasonable, but in fact it breaks
  300. certificate authentication with some servers. If
  301. they give an HTTP/1.0 response, even if they
  302. explicitly give a Connection: Keep-Alive header,
  303. just close the connection. */
  304. else if (!strcasecmp(colon, "Keep-Alive"))
  305. closeconn = 0;
  306. #endif
  307. }
  308. if (!strcasecmp(hdrline, "Location")) {
  309. vpninfo->redirect_url = strdup(colon);
  310. if (!vpninfo->redirect_url) {
  311. ret = -ENOMEM;
  312. goto err;
  313. }
  314. }
  315. if (!strcasecmp(hdrline, "Content-Length")) {
  316. bodylen = atoi(colon);
  317. if (bodylen < 0) {
  318. vpn_progress(vpninfo, PRG_ERR,
  319. _("Response body has negative size (%d)\n"),
  320. bodylen);
  321. ret = -EINVAL;
  322. goto err;
  323. }
  324. }
  325. if (!strcasecmp(hdrline, "Transfer-Encoding")) {
  326. if (!strcasecmp(colon, "chunked"))
  327. bodylen = BODY_CHUNKED;
  328. else {
  329. vpn_progress(vpninfo, PRG_ERR,
  330. _("Unknown Transfer-Encoding: %s\n"),
  331. colon);
  332. ret = -EINVAL;
  333. goto err;
  334. }
  335. }
  336. if (header_cb)
  337. header_cb(vpninfo, hdrline, colon);
  338. }
  339. /* Handle 'HTTP/1.1 100 Continue'. Not that we should ever see it */
  340. if (result == 100)
  341. goto cont;
  342. /* On successful CONNECT or upgrade, there is no body. Return success */
  343. if (connect && (result == 200 || result == 101)) {
  344. buf_free(hdrbuf);
  345. return result;
  346. }
  347. /* Now the body, if there is one */
  348. vpn_progress(vpninfo, PRG_DEBUG, _("HTTP body %s (%d)\n"),
  349. bodylen == BODY_HTTP10 ? "http 1.0" :
  350. bodylen == BODY_CHUNKED ? "chunked" : "length: ",
  351. bodylen);
  352. /* If we were given Content-Length, it's nice and easy... */
  353. if (bodylen > 0) {
  354. if (buf_ensure_space(body, bodylen + 1)) {
  355. ret = buf_error(body);
  356. goto err;
  357. }
  358. while (body->pos < bodylen) {
  359. i = vpninfo->ssl_read(vpninfo, body->data + body->pos, bodylen - body->pos);
  360. if (i < 0) {
  361. vpn_progress(vpninfo, PRG_ERR,
  362. _("Error reading HTTP response body\n"));
  363. ret = i;
  364. goto err;
  365. }
  366. body->pos += i;
  367. }
  368. } else if (bodylen == BODY_CHUNKED) {
  369. char clen_buf[16];
  370. /* ... else, chunked */
  371. while ((i = vpninfo->ssl_gets(vpninfo, clen_buf, sizeof(clen_buf)))) {
  372. int lastchunk = 0;
  373. long chunklen;
  374. if (i < 0) {
  375. vpn_progress(vpninfo, PRG_ERR,
  376. _("Error fetching chunk header\n"));
  377. ret = i;
  378. goto err;
  379. }
  380. chunklen = strtol(clen_buf, NULL, 16);
  381. if (!chunklen) {
  382. lastchunk = 1;
  383. goto skip;
  384. }
  385. if (chunklen < 0) {
  386. vpn_progress(vpninfo, PRG_ERR,
  387. _("HTTP chunk length is negative (%ld)\n"), chunklen);
  388. ret = -EINVAL;
  389. goto err;
  390. }
  391. if (chunklen >= INT_MAX) {
  392. vpn_progress(vpninfo, PRG_ERR,
  393. _("HTTP chunk length is too large (%ld)\n"), chunklen);
  394. ret = -EINVAL;
  395. goto err;
  396. }
  397. if (buf_ensure_space(body, chunklen + 1)) {
  398. ret = buf_error(body);
  399. goto err;
  400. }
  401. while (chunklen) {
  402. i = vpninfo->ssl_read(vpninfo, body->data + body->pos, chunklen);
  403. if (i < 0) {
  404. vpn_progress(vpninfo, PRG_ERR,
  405. _("Error reading HTTP response body\n"));
  406. ret = i;
  407. goto err;
  408. }
  409. chunklen -= i;
  410. body->pos += i;
  411. }
  412. skip:
  413. if ((i = vpninfo->ssl_gets(vpninfo, clen_buf, sizeof(clen_buf)))) {
  414. if (i < 0) {
  415. vpn_progress(vpninfo, PRG_ERR,
  416. _("Error fetching HTTP response body\n"));
  417. ret = i;
  418. } else {
  419. vpn_progress(vpninfo, PRG_ERR,
  420. _("Error in chunked decoding. Expected '', got: '%s'\n"),
  421. clen_buf);
  422. ret = -EINVAL;
  423. }
  424. goto err;
  425. }
  426. if (lastchunk)
  427. break;
  428. }
  429. } else if (bodylen == BODY_HTTP10) {
  430. if (!closeconn) {
  431. vpn_progress(vpninfo, PRG_ERR,
  432. _("Cannot receive HTTP 1.0 body without closing connection\n"));
  433. openconnect_close_https(vpninfo, 0);
  434. buf_free(hdrbuf);
  435. return -EINVAL;
  436. }
  437. /* HTTP 1.0 response. Just eat all we can in 4KiB chunks */
  438. while (1) {
  439. if (buf_ensure_space(body, 4096 + 1)) {
  440. ret = buf_error(body);
  441. goto err;
  442. }
  443. i = vpninfo->ssl_read(vpninfo, body->data + body->pos, 4096);
  444. if (i < 0) {
  445. /* Error */
  446. ret = i;
  447. goto err;
  448. } else if (!i)
  449. break;
  450. /* Got more data */
  451. body->pos += i;
  452. }
  453. }
  454. if (body && body->data)
  455. body->data[body->pos] = 0;
  456. ret = result;
  457. if (closeconn || vpninfo->no_http_keepalive) {
  458. err:
  459. openconnect_close_https(vpninfo, 0);
  460. }
  461. buf_free(hdrbuf);
  462. return ret;
  463. }
  464. int internal_parse_url(const char *url, char **res_proto, char **res_host,
  465. int *res_port, char **res_path, int default_port)
  466. {
  467. const char *orig_host, *orig_path;
  468. char *host, *port_str;
  469. int port, proto_len = 0;
  470. orig_host = strstr(url, "://");
  471. if (orig_host) {
  472. proto_len = orig_host - url;
  473. orig_host += 3;
  474. if (strprefix_match(url, proto_len, "https"))
  475. port = 443;
  476. else if (strprefix_match(url, proto_len, "http"))
  477. port = 80;
  478. else if (strprefix_match(url, proto_len, "socks") ||
  479. strprefix_match(url, proto_len, "socks4") ||
  480. strprefix_match(url, proto_len, "socks5"))
  481. port = 1080;
  482. else
  483. return -EPROTONOSUPPORT;
  484. } else {
  485. if (default_port) {
  486. port = default_port;
  487. orig_host = url;
  488. } else
  489. return -EINVAL;
  490. }
  491. orig_path = strchr(orig_host, '/');
  492. if (orig_path) {
  493. host = strndup(orig_host, orig_path - orig_host);
  494. orig_path++;
  495. } else
  496. host = strdup(orig_host);
  497. if (!host)
  498. return -ENOMEM;
  499. port_str = strrchr(host, ':');
  500. if (port_str) {
  501. char *end;
  502. int new_port = strtol(port_str + 1, &end, 10);
  503. if (!*end) {
  504. *port_str = 0;
  505. port = new_port;
  506. if (port <= 0 || port > 0xffff) {
  507. free(host);
  508. return -EINVAL;
  509. }
  510. }
  511. }
  512. if (res_proto)
  513. *res_proto = proto_len ? strndup(url, proto_len) : NULL;
  514. if (res_host)
  515. *res_host = host;
  516. else
  517. free(host);
  518. if (res_port)
  519. *res_port = port;
  520. if (res_path)
  521. *res_path = (orig_path && *orig_path) ? strdup(orig_path) : NULL;
  522. return 0;
  523. }
  524. char *internal_get_url(struct openconnect_info *vpninfo)
  525. {
  526. struct oc_text_buf *buf = buf_alloc();
  527. char *url;
  528. buf_append(buf, "https://%s", vpninfo->hostname);
  529. if (vpninfo->port != 443)
  530. buf_append(buf, ":%d", vpninfo->port);
  531. buf_append(buf, "/");
  532. if (vpninfo->urlpath)
  533. buf_append(buf, "%s", vpninfo->urlpath);
  534. if (buf_error(buf)) {
  535. buf_free(buf);
  536. return NULL;
  537. } else {
  538. url = buf->data;
  539. buf->data = NULL;
  540. buf_free(buf);
  541. return url;
  542. }
  543. }
  544. void openconnect_clear_cookies(struct openconnect_info *vpninfo)
  545. {
  546. struct oc_vpn_option *opt, *next;
  547. for (opt = vpninfo->cookies; opt; opt = next) {
  548. next = opt->next;
  549. free(opt->option);
  550. free(opt->value);
  551. free(opt);
  552. }
  553. vpninfo->cookies = NULL;
  554. }
  555. /* Return value:
  556. * < 0, on error
  557. * = 0, on success (go ahead and retry with the latest vpninfo->{hostname,urlpath,port,...})
  558. */
  559. int handle_redirect(struct openconnect_info *vpninfo)
  560. {
  561. vpninfo->redirect_type = REDIR_TYPE_LOCAL;
  562. if (!strncmp(vpninfo->redirect_url, "https://", 8)) {
  563. /* New host. Tear down the existing connection and make a new one */
  564. char *host;
  565. int port;
  566. int ret;
  567. free(vpninfo->urlpath);
  568. vpninfo->urlpath = NULL;
  569. ret = internal_parse_url(vpninfo->redirect_url, NULL, &host, &port, &vpninfo->urlpath, 0);
  570. if (ret) {
  571. vpn_progress(vpninfo, PRG_ERR,
  572. _("Failed to parse redirected URL '%s': %s\n"),
  573. vpninfo->redirect_url, strerror(-ret));
  574. free(vpninfo->redirect_url);
  575. vpninfo->redirect_url = NULL;
  576. return ret;
  577. }
  578. if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
  579. openconnect_set_hostname(vpninfo, host);
  580. vpninfo->port = port;
  581. /* Kill the existing connection, and a new one will happen */
  582. openconnect_close_https(vpninfo, 0);
  583. openconnect_clear_cookies(vpninfo);
  584. vpninfo->redirect_type = REDIR_TYPE_NEWHOST;
  585. }
  586. free(host);
  587. free(vpninfo->redirect_url);
  588. vpninfo->redirect_url = NULL;
  589. return 0;
  590. } else if (vpninfo->redirect_url[0] == '/') {
  591. /* Absolute redirect within same host */
  592. free(vpninfo->urlpath);
  593. vpninfo->urlpath = strdup(vpninfo->redirect_url + 1);
  594. free(vpninfo->redirect_url);
  595. vpninfo->redirect_url = NULL;
  596. return 0;
  597. } else if (strstr(vpninfo->redirect_url, "://")) {
  598. vpn_progress(vpninfo, PRG_ERR,
  599. _("Cannot follow redirection to non-https URL '%s'\n"),
  600. vpninfo->redirect_url);
  601. free(vpninfo->redirect_url);
  602. vpninfo->redirect_url = NULL;
  603. return -EINVAL;
  604. } else {
  605. char *lastslash = NULL;
  606. if (vpninfo->urlpath)
  607. lastslash = strrchr(vpninfo->urlpath, '/');
  608. if (!lastslash) {
  609. free(vpninfo->urlpath);
  610. vpninfo->urlpath = vpninfo->redirect_url;
  611. vpninfo->redirect_url = NULL;
  612. } else {
  613. char *oldurl = vpninfo->urlpath;
  614. *lastslash = 0;
  615. vpninfo->urlpath = NULL;
  616. if (asprintf(&vpninfo->urlpath, "%s/%s",
  617. oldurl, vpninfo->redirect_url) == -1) {
  618. int err = -errno;
  619. vpn_progress(vpninfo, PRG_ERR,
  620. _("Allocating new path for relative redirect failed: %s\n"),
  621. strerror(-err));
  622. return err;
  623. }
  624. free(oldurl);
  625. free(vpninfo->redirect_url);
  626. vpninfo->redirect_url = NULL;
  627. }
  628. return 0;
  629. }
  630. }
  631. void do_dump_buf(struct openconnect_info *vpninfo, char prefix, char *buf)
  632. {
  633. while (*buf) {
  634. char *eol = buf;
  635. char eol_char = 0;
  636. while (*eol) {
  637. if (*eol == '\r' || *eol == '\n') {
  638. eol_char = *eol;
  639. *eol = 0;
  640. break;
  641. }
  642. eol++;
  643. }
  644. vpn_progress(vpninfo, PRG_DEBUG, "%c %s\n", prefix, buf);
  645. if (!eol_char)
  646. break;
  647. *eol = eol_char;
  648. buf = eol + 1;
  649. if (eol_char == '\r' && *buf == '\n')
  650. buf++;
  651. }
  652. }
  653. void do_dump_buf_hex(struct openconnect_info *vpninfo, int loglevel, char prefix, unsigned char *buf, int len)
  654. {
  655. struct oc_text_buf *line = buf_alloc();
  656. int i;
  657. for (i = 0; i < len; i+=16) {
  658. int j;
  659. buf_truncate(line);
  660. buf_append(line, "%04x:", i);
  661. for (j = i; j < i+16; j++) {
  662. if (!(j & 7))
  663. buf_append(line, " ");
  664. if (j < len)
  665. buf_append(line, " %02x", buf[j]);
  666. else
  667. buf_append(line, " ");
  668. }
  669. buf_append(line, " |");
  670. for (j = i; j < i+16 && j < len; j++)
  671. buf_append(line, "%c", isprint(buf[j])? buf[j] : '.');
  672. buf_append(line, "|");
  673. if (buf_error(line))
  674. break;
  675. vpn_progress(vpninfo, loglevel, "%c %s\n", prefix, line->data);
  676. }
  677. buf_free(line);
  678. }
  679. static int https_socket_closed(struct openconnect_info *vpninfo)
  680. {
  681. char c;
  682. if (!openconnect_https_connected(vpninfo))
  683. return 1;
  684. if (recv(vpninfo->ssl_fd, &c, 1, MSG_PEEK) == 0) {
  685. vpn_progress(vpninfo, PRG_DEBUG,
  686. _("HTTPS socket closed by peer; reopening\n"));
  687. openconnect_close_https(vpninfo, 0);
  688. return 1;
  689. }
  690. return 0;
  691. }
  692. /* Inputs:
  693. * method: GET or POST
  694. * vpninfo->hostname: Host DNS name
  695. * vpninfo->port: TCP port, typically 443
  696. * vpninfo->urlpath: Relative path, e.g. /+webvpn+/foo.html
  697. * request_body_type: Content type for a POST (e.g. text/html). Can be NULL.
  698. * request_body: POST content
  699. * form_buf: Callee-allocated buffer for server content
  700. * header_cb: Callback executed on every header line
  701. * If HTTP authentication is needed, the callback specified needs to call http_auth_hdrs.
  702. * flags (bitfield): HTTP_REDIRECT: follow redirects;
  703. * HTTP_REDIRECT_TO_GET: follow redirects, but change POST to GET;
  704. * HTTP_BODY_ON_ERR: return server content in form_buf even on error
  705. *
  706. * Return value:
  707. * < 0, on error
  708. * >=0, on success, indicating the length of the data in *form_buf
  709. */
  710. int do_https_request(struct openconnect_info *vpninfo, const char *method, const char *request_body_type,
  711. struct oc_text_buf *request_body, char **form_buf,
  712. int (*header_cb)(struct openconnect_info *, char *, char *), int flags)
  713. {
  714. struct oc_text_buf *buf;
  715. int result;
  716. int rq_retry;
  717. int rlen, pad;
  718. int i, auth = 0;
  719. int max_redirects = 10;
  720. if (!header_cb)
  721. header_cb = http_auth_hdrs;
  722. if (request_body_type && buf_error(request_body))
  723. return buf_error(request_body);
  724. buf = buf_alloc();
  725. redirected:
  726. if (max_redirects-- <= 0) {
  727. result = -EIO;
  728. goto out;
  729. }
  730. vpninfo->redirect_type = REDIR_TYPE_NONE;
  731. if (*form_buf) {
  732. free(*form_buf);
  733. *form_buf = NULL;
  734. }
  735. /*
  736. * A long time ago, I *wanted* to use an HTTP client library like cURL
  737. * for this. But we need a *lot* of control over the underlying SSL
  738. * transport, and we also have to do horrid tricks like the Juniper NC
  739. * 'GET' request that actually behaves like a 'CONNECT'.
  740. *
  741. * So the world gained Yet Another HTTP Implementation. Sorry.
  742. *
  743. */
  744. buf_truncate(buf);
  745. buf_append(buf, "%s /%s HTTP/1.1\r\n", method, vpninfo->urlpath ?: "");
  746. if (auth) {
  747. result = gen_authorization_hdr(vpninfo, 0, buf);
  748. if (result)
  749. goto out;
  750. /* Forget existing challenges */
  751. clear_auth_states(vpninfo, vpninfo->http_auth, 0);
  752. }
  753. if (vpninfo->proto->add_http_headers)
  754. vpninfo->proto->add_http_headers(vpninfo, buf);
  755. if (request_body_type) {
  756. rlen = request_body->pos;
  757. /* force body length to be a multiple of 64, to avoid leaking
  758. * password length. */
  759. pad = 64*(1+rlen/64) - rlen;
  760. buf_append(buf, "X-Pad: %0*d\r\n", pad, 0);
  761. buf_append(buf, "Content-Type: %s\r\n", request_body_type);
  762. buf_append(buf, "Content-Length: %d\r\n", (int)rlen);
  763. }
  764. buf_append(buf, "\r\n");
  765. if (request_body_type)
  766. buf_append_bytes(buf, request_body->data, request_body->pos);
  767. if (vpninfo->port == 443)
  768. vpn_progress(vpninfo, PRG_INFO, "%s https://%s/%s\n",
  769. method, vpninfo->hostname,
  770. vpninfo->urlpath ?: "");
  771. else
  772. vpn_progress(vpninfo, PRG_INFO, "%s https://%s:%d/%s\n",
  773. method, vpninfo->hostname, vpninfo->port,
  774. vpninfo->urlpath ?: "");
  775. if (buf_error(buf))
  776. return buf_free(buf);
  777. vpninfo->retry_on_auth_fail = 0;
  778. retry:
  779. if (!https_socket_closed(vpninfo)) {
  780. /* The session is already connected. If we get a failure on
  781. * *sending* the request, try it again immediately with a new
  782. * connection. */
  783. rq_retry = 1;
  784. } else {
  785. rq_retry = 0;
  786. if ((openconnect_open_https(vpninfo))) {
  787. vpn_progress(vpninfo, PRG_ERR,
  788. _("Failed to open HTTPS connection to %s\n"),
  789. vpninfo->hostname);
  790. /* We really don't want to return -EINVAL if we have
  791. failed to even connect to the server, because if
  792. we do that openconnect_obtain_cookie() might try
  793. again without XMLPOST... with the same result. */
  794. result = -EIO;
  795. goto out;
  796. }
  797. }
  798. if (vpninfo->dump_http_traffic)
  799. dump_buf(vpninfo, '>', buf->data);
  800. for (i = 0; i < buf->pos; i += 16384) {
  801. result = vpninfo->ssl_write(vpninfo, buf->data + i, MIN(buf->pos - i, 16384) );
  802. if (result < 0) {
  803. if (rq_retry) {
  804. /* Retry if we failed to send the request on
  805. an already-open connection */
  806. openconnect_close_https(vpninfo, 0);
  807. goto retry;
  808. }
  809. /* We'll already have complained about whatever offended us */
  810. goto out;
  811. }
  812. }
  813. result = process_http_response(vpninfo, 0, header_cb, buf);
  814. if (result < 0) {
  815. if (rq_retry) {
  816. openconnect_close_https(vpninfo, 0);
  817. vpn_progress(vpninfo, PRG_INFO,
  818. _("Retrying failed %s request on new connection\n"),
  819. method);
  820. /* All the way back to 'redirected' since we need to rebuild
  821. * the request in 'buf' from scratch. */
  822. goto redirected;
  823. }
  824. goto out;
  825. }
  826. if (vpninfo->dump_http_traffic && buf->pos)
  827. dump_buf(vpninfo, '<', buf->data);
  828. if (result == 401 && vpninfo->try_http_auth) {
  829. auth = 1;
  830. goto redirected;
  831. }
  832. if (result != 200 && vpninfo->redirect_url) {
  833. result = handle_redirect(vpninfo);
  834. if (result == 0) {
  835. if (!(flags & (HTTP_REDIRECT | HTTP_REDIRECT_TO_GET)))
  836. goto out;
  837. if (flags & HTTP_REDIRECT_TO_GET) {
  838. /* Some protocols require a GET after a redirected POST */
  839. method = "GET";
  840. request_body_type = NULL;
  841. }
  842. if (vpninfo->redirect_type == REDIR_TYPE_NEWHOST)
  843. clear_auth_states(vpninfo, vpninfo->http_auth, 1);
  844. goto redirected;
  845. }
  846. goto out;
  847. }
  848. if (!buf->pos || result != 200) {
  849. vpn_progress(vpninfo, PRG_ERR,
  850. _("Unexpected %d result from server\n"),
  851. result);
  852. if (result == 401 || result == 403)
  853. result = -EPERM;
  854. else if (result == 512) /* GlobalProtect invalid username/password */
  855. result = -EACCES;
  856. else
  857. result = -EINVAL;
  858. if (!buf->pos || !(flags & HTTP_BODY_ON_ERROR))
  859. goto out;
  860. } else
  861. result = buf->pos;
  862. *form_buf = buf->data;
  863. buf->data = NULL;
  864. out:
  865. buf_free(buf);
  866. /* On success, clear out all authentication state for the next request */
  867. clear_auth_states(vpninfo, vpninfo->http_auth, 1);
  868. return result;
  869. }
  870. char *openconnect_create_useragent(const char *base)
  871. {
  872. char *uagent;
  873. if (asprintf(&uagent, "%s %s", base, openconnect_version_str) < 0)
  874. return NULL;
  875. return uagent;
  876. }
  877. static int proxy_gets(struct openconnect_info *vpninfo, char *buf, size_t len)
  878. {
  879. return cancellable_gets(vpninfo, vpninfo->proxy_fd, buf, len);
  880. }
  881. static int proxy_write(struct openconnect_info *vpninfo, char *buf, size_t len)
  882. {
  883. return cancellable_send(vpninfo, vpninfo->proxy_fd, buf, len);
  884. }
  885. static int proxy_read(struct openconnect_info *vpninfo, char *buf, size_t len)
  886. {
  887. return cancellable_recv(vpninfo, vpninfo->proxy_fd, buf, len);
  888. }
  889. static const char * const socks_errors[] = {
  890. N_("request granted"),
  891. N_("general failure"),
  892. N_("connection not allowed by ruleset"),
  893. N_("network unreachable"),
  894. N_("host unreachable"),
  895. N_("connection refused by destination host"),
  896. N_("TTL expired"),
  897. N_("command not supported / protocol error"),
  898. N_("address type not supported")
  899. };
  900. static int socks_password_auth(struct openconnect_info *vpninfo)
  901. {
  902. int ul, pl, i;
  903. char buf[1024];
  904. if (!vpninfo->proxy_user || !vpninfo->proxy_pass) {
  905. vpn_progress(vpninfo, PRG_ERR,
  906. _("SOCKS server requested username/password but we have none\n"));
  907. return -EIO;
  908. }
  909. ul = strlen(vpninfo->proxy_user);
  910. pl = strlen(vpninfo->proxy_pass);
  911. if (ul > 255 || pl > 255) {
  912. vpn_progress(vpninfo, PRG_ERR,
  913. _("Username and password for SOCKS authentication must be < 255 bytes\n"));
  914. return -EINVAL;
  915. }
  916. buf[0] = 1;
  917. buf[1] = ul;
  918. memcpy(buf + 2, vpninfo->proxy_user, ul);
  919. buf[2 + ul] = pl;
  920. memcpy(buf + 3 + ul, vpninfo->proxy_pass, pl);
  921. i = proxy_write(vpninfo, buf, 3 + ul + pl);
  922. /* Don't leave passwords lying around if we can easily avoid it... */
  923. memset(buf, 0, sizeof(buf));
  924. if (i < 0) {
  925. vpn_progress(vpninfo, PRG_ERR,
  926. _("Error writing auth request to SOCKS proxy: %s\n"),
  927. strerror(-i));
  928. return i;
  929. }
  930. if ((i = proxy_read(vpninfo, buf, 2)) < 0) {
  931. vpn_progress(vpninfo, PRG_ERR,
  932. _("Error reading auth response from SOCKS proxy: %s\n"),
  933. strerror(-i));
  934. return i;
  935. }
  936. if (buf[0] != 1) {
  937. vpn_progress(vpninfo, PRG_ERR,
  938. _("Unexpected auth response from SOCKS proxy: %02x %02x\n"),
  939. buf[0], buf[1]);
  940. return -EIO;
  941. }
  942. if (buf[1] == 0) {
  943. vpn_progress(vpninfo, PRG_DEBUG,
  944. _("Authenticated to SOCKS server using password\n"));
  945. return 0;
  946. } else {
  947. vpn_progress(vpninfo, PRG_ERR,
  948. _("Password authentication to SOCKS server failed\n"));
  949. return -EIO;
  950. }
  951. }
  952. #define SOCKS_AUTH_NONE 0 /* RFC1928 */
  953. #define SOCKS_AUTH_GSSAPI 1 /* RFC1961 */
  954. #define SOCKS_AUTH_PASSWORD 2 /* RFC1929 */
  955. #define SOCKS_AUTH_NO_ACCEPTABLE 0xff /* RFC1928 */
  956. static int process_socks_proxy(struct openconnect_info *vpninfo)
  957. {
  958. char buf[1024];
  959. int i, nr_auth_methods = 0;
  960. buf[0] = 5; /* SOCKS version */
  961. buf[2 + nr_auth_methods++] = SOCKS_AUTH_NONE;
  962. #if defined(HAVE_GSSAPI) || defined(_WIN32)
  963. if (vpninfo->proxy_auth[AUTH_TYPE_GSSAPI].state > AUTH_FAILED &&
  964. !vpninfo->proxy_user && !vpninfo->proxy_pass)
  965. buf[2 + nr_auth_methods++] = SOCKS_AUTH_GSSAPI;
  966. #endif
  967. /*
  968. * Basic auth is disabled by default. But for SOCKS, if the user has
  969. * actually provided a password then that should implicitly allow
  970. * basic auth since that's all that SOCKS can do. We shouldn't force
  971. * the user to also add --proxy-auth=basic on the command line.
  972. */
  973. if ((vpninfo->proxy_auth[AUTH_TYPE_BASIC].state > AUTH_FAILED ||
  974. vpninfo->proxy_auth[AUTH_TYPE_BASIC].state == AUTH_DEFAULT_DISABLED) &&
  975. vpninfo->proxy_user && vpninfo->proxy_pass)
  976. buf[2 + nr_auth_methods++] = SOCKS_AUTH_PASSWORD;
  977. buf[1] = nr_auth_methods;
  978. if ((i = proxy_write(vpninfo, buf, 2 + nr_auth_methods)) < 0) {
  979. vpn_progress(vpninfo, PRG_ERR,
  980. _("Error writing auth request to SOCKS proxy: %s\n"),
  981. strerror(-i));
  982. return i;
  983. }
  984. if ((i = proxy_read(vpninfo, buf, 2)) < 0) {
  985. vpn_progress(vpninfo, PRG_ERR,
  986. _("Error reading auth response from SOCKS proxy: %s\n"),
  987. strerror(-i));
  988. return i;
  989. }
  990. if (buf[0] != 5) {
  991. vpn_progress(vpninfo, PRG_ERR,
  992. _("Unexpected auth response from SOCKS proxy: %02x %02x\n"),
  993. buf[0], buf[1]);
  994. return -EIO;
  995. }
  996. switch ((unsigned char)buf[1]) {
  997. case SOCKS_AUTH_NONE:
  998. /* No authentication */
  999. break;
  1000. case SOCKS_AUTH_GSSAPI:
  1001. #if defined(HAVE_GSSAPI) || defined(_WIN32)
  1002. vpn_progress(vpninfo, PRG_DEBUG,
  1003. _("SOCKS server requested GSSAPI authentication\n"));
  1004. if (socks_gssapi_auth(vpninfo))
  1005. return -EIO;
  1006. break;
  1007. #else
  1008. /* This should never happen since we didn't ask for it! */
  1009. vpn_progress(vpninfo, PRG_ERR,
  1010. _("SOCKS server requested GSSAPI authentication\n"));
  1011. return -EIO;
  1012. #endif
  1013. case SOCKS_AUTH_PASSWORD:
  1014. vpn_progress(vpninfo, PRG_DEBUG,
  1015. _("SOCKS server requested password authentication\n"));
  1016. if (socks_password_auth(vpninfo))
  1017. return -EIO;
  1018. break;
  1019. case SOCKS_AUTH_NO_ACCEPTABLE:
  1020. vpn_progress(vpninfo, PRG_ERR,
  1021. _("SOCKS server requires authentication\n"));
  1022. #if !defined(HAVE_GSSAPI) && !defined(_WIN32)
  1023. vpn_progress(vpninfo, PRG_INFO,
  1024. _("This version of OpenConnect was built without GSSAPI support\n"));
  1025. #endif
  1026. return -EIO;
  1027. default:
  1028. vpn_progress(vpninfo, PRG_ERR,
  1029. _("SOCKS server requested unknown authentication type %02x\n"),
  1030. (unsigned char)buf[1]);
  1031. return -EIO;
  1032. }
  1033. vpn_progress(vpninfo, PRG_INFO,
  1034. _("Requesting SOCKS proxy connection to %s:%d\n"),
  1035. vpninfo->hostname, vpninfo->port);
  1036. buf[0] = 5; /* SOCKS version */
  1037. buf[1] = 1; /* CONNECT */
  1038. buf[2] = 0; /* Reserved */
  1039. buf[3] = 3; /* Address type is domain name */
  1040. buf[4] = strlen(vpninfo->hostname);
  1041. strcpy((char *)buf + 5, vpninfo->hostname);
  1042. i = strlen(vpninfo->hostname) + 5;
  1043. store_be16(buf + i, vpninfo->port);
  1044. i += 2;
  1045. if ((i = proxy_write(vpninfo, buf, i)) < 0) {
  1046. vpn_progress(vpninfo, PRG_ERR,
  1047. _("Error writing connect request to SOCKS proxy: %s\n"),
  1048. strerror(-i));
  1049. return i;
  1050. }
  1051. /* Read 5 bytes -- up to and including the first byte of the returned
  1052. address (which might be the length byte of a domain name) */
  1053. if ((i = proxy_read(vpninfo, buf, 5)) < 0) {
  1054. vpn_progress(vpninfo, PRG_ERR,
  1055. _("Error reading connect response from SOCKS proxy: %s\n"),
  1056. strerror(-i));
  1057. return i;
  1058. }
  1059. if (i != 5 || buf[0] != 5) {
  1060. vpn_progress(vpninfo, PRG_ERR,
  1061. _("Unexpected connect response from SOCKS proxy: %02x %02x...\n"),
  1062. buf[0], buf[1]);
  1063. return -EIO;
  1064. }
  1065. if (buf[1]) {
  1066. unsigned char err = buf[1];
  1067. if (err < ARRAY_SIZE(socks_errors))
  1068. vpn_progress(vpninfo, PRG_ERR,
  1069. _("SOCKS proxy error %02x: %s\n"),
  1070. err, _(socks_errors[err]));
  1071. else
  1072. vpn_progress(vpninfo, PRG_ERR,
  1073. _("SOCKS proxy error %02x\n"), err);
  1074. return -EIO;
  1075. }
  1076. /* Connect responses contain an address */
  1077. switch (buf[3]) {
  1078. case 1: /* Legacy IP */
  1079. i = 5;
  1080. break;
  1081. case 3: /* Domain name */
  1082. i = buf[4] + 2;
  1083. break;
  1084. case 4: /* IPv6 */
  1085. i = 17;
  1086. break;
  1087. default:
  1088. vpn_progress(vpninfo, PRG_ERR,
  1089. _("Unexpected address type %02x in SOCKS connect response\n"),
  1090. buf[3]);
  1091. return -EIO;
  1092. }
  1093. if ((i = proxy_read(vpninfo, buf, i)) < 0) {
  1094. vpn_progress(vpninfo, PRG_ERR,
  1095. _("Error reading connect response from SOCKS proxy: %s\n"),
  1096. strerror(-i));
  1097. return i;
  1098. }
  1099. return 0;
  1100. }
  1101. static int process_http_proxy(struct openconnect_info *vpninfo)
  1102. {
  1103. struct oc_text_buf *reqbuf;
  1104. int result;
  1105. int auth = vpninfo->proxy_close_during_auth;
  1106. vpninfo->proxy_close_during_auth = 0;
  1107. vpn_progress(vpninfo, PRG_INFO,
  1108. _("Requesting HTTP proxy connection to %s:%d\n"),
  1109. vpninfo->hostname, vpninfo->port);
  1110. retry:
  1111. reqbuf = buf_alloc();
  1112. buf_append(reqbuf, "CONNECT %s:%d HTTP/1.1\r\n", vpninfo->hostname, vpninfo->port);
  1113. if (vpninfo->port == 443)
  1114. buf_append(reqbuf, "Host: %s\r\n", vpninfo->hostname);
  1115. else
  1116. buf_append(reqbuf, "Host: %s:%d\r\n", vpninfo->hostname, vpninfo->port);
  1117. buf_append(reqbuf, "User-Agent: %s\r\n", vpninfo->useragent);
  1118. buf_append(reqbuf, "Proxy-Connection: keep-alive\r\n");
  1119. buf_append(reqbuf, "Connection: keep-alive\r\n");
  1120. buf_append(reqbuf, "Accept-Encoding: identity\r\n");
  1121. if (auth) {
  1122. result = gen_authorization_hdr(vpninfo, 1, reqbuf);
  1123. if (result) {
  1124. buf_free(reqbuf);
  1125. return result;
  1126. }
  1127. /* Forget existing challenges */
  1128. clear_auth_states(vpninfo, vpninfo->proxy_auth, 0);
  1129. }
  1130. buf_append(reqbuf, "\r\n");
  1131. if (buf_error(reqbuf))
  1132. return buf_free(reqbuf);
  1133. if (vpninfo->dump_http_traffic)
  1134. dump_buf(vpninfo, '>', reqbuf->data);
  1135. result = proxy_write(vpninfo, reqbuf->data, reqbuf->pos);
  1136. if (result < 0) {
  1137. buf_free(reqbuf);
  1138. vpn_progress(vpninfo, PRG_ERR,
  1139. _("Sending proxy request failed: %s\n"),
  1140. strerror(-result));
  1141. return result;
  1142. }
  1143. result = process_http_response(vpninfo, 1, proxy_auth_hdrs, reqbuf);
  1144. buf_free(reqbuf);
  1145. if (result < 0)
  1146. return -EINVAL;
  1147. if (result == 407) {
  1148. /* If the proxy asked us to close the connection, do so */
  1149. if (vpninfo->proxy_close_during_auth)
  1150. return -EAGAIN;
  1151. auth = 1;
  1152. goto retry;
  1153. }
  1154. if (result == 200)
  1155. return 0;
  1156. vpn_progress(vpninfo, PRG_ERR,
  1157. _("Proxy CONNECT request failed: %d\n"), result);
  1158. return -EIO;
  1159. }
  1160. int process_proxy(struct openconnect_info *vpninfo, int ssl_sock)
  1161. {
  1162. int ret;
  1163. vpninfo->proxy_fd = ssl_sock;
  1164. vpninfo->ssl_read = proxy_read;
  1165. vpninfo->ssl_write = proxy_write;
  1166. vpninfo->ssl_gets = proxy_gets;
  1167. if (!vpninfo->proxy_type || !strcmp(vpninfo->proxy_type, "http"))
  1168. ret = process_http_proxy(vpninfo);
  1169. else if (!strcmp(vpninfo->proxy_type, "socks") ||
  1170. !strcmp(vpninfo->proxy_type, "socks5"))
  1171. ret = process_socks_proxy(vpninfo);
  1172. else {
  1173. vpn_progress(vpninfo, PRG_ERR, _("Unknown proxy type '%s'\n"),
  1174. vpninfo->proxy_type);
  1175. ret = -EIO;
  1176. }
  1177. vpninfo->proxy_fd = -1;
  1178. if (!vpninfo->proxy_close_during_auth)
  1179. clear_auth_states(vpninfo, vpninfo->proxy_auth, 1);
  1180. return ret;
  1181. }
  1182. int openconnect_set_http_proxy(struct openconnect_info *vpninfo,
  1183. const char *proxy)
  1184. {
  1185. char *p;
  1186. int ret;
  1187. free(vpninfo->proxy_type);
  1188. vpninfo->proxy_type = NULL;
  1189. free(vpninfo->proxy);
  1190. vpninfo->proxy = NULL;
  1191. ret = internal_parse_url(proxy, &vpninfo->proxy_type, &vpninfo->proxy,
  1192. &vpninfo->proxy_port, NULL, 80);
  1193. if (ret) {
  1194. vpn_progress(vpninfo, PRG_ERR, _("Failed to parse proxy '%s'\n"), proxy);
  1195. return ret;
  1196. }
  1197. p = strrchr(vpninfo->proxy, '@');
  1198. if (p) {
  1199. /* Proxy username/password */
  1200. *p = 0;
  1201. vpninfo->proxy_user = vpninfo->proxy;
  1202. vpninfo->proxy = strdup(p + 1);
  1203. p = strchr(vpninfo->proxy_user, ':');
  1204. if (p) {
  1205. *p = 0;
  1206. vpninfo->proxy_pass = strdup(p + 1);
  1207. xmlURIUnescapeString(vpninfo->proxy_pass, 0, vpninfo->proxy_pass);
  1208. }
  1209. xmlURIUnescapeString(vpninfo->proxy_user, 0, vpninfo->proxy_user);
  1210. }
  1211. if (vpninfo->proxy_type &&
  1212. strcmp(vpninfo->proxy_type, "http") &&
  1213. strcmp(vpninfo->proxy_type, "socks") &&
  1214. strcmp(vpninfo->proxy_type, "socks5")) {
  1215. vpn_progress(vpninfo, PRG_ERR,
  1216. _("Only http or socks(5) proxies supported\n"));
  1217. free(vpninfo->proxy_type);
  1218. vpninfo->proxy_type = NULL;
  1219. free(vpninfo->proxy);
  1220. vpninfo->proxy = NULL;
  1221. return -EINVAL;
  1222. }
  1223. return 0;
  1224. }
  1225. void http_common_headers(struct openconnect_info *vpninfo, struct oc_text_buf *buf)
  1226. {
  1227. struct oc_vpn_option *opt;
  1228. if (vpninfo->port == 443)
  1229. buf_append(buf, "Host: %s\r\n", vpninfo->hostname);
  1230. else
  1231. buf_append(buf, "Host: %s:%d\r\n", vpninfo->hostname, vpninfo->port);
  1232. buf_append(buf, "User-Agent: %s\r\n", vpninfo->useragent);
  1233. if (vpninfo->cookies) {
  1234. buf_append(buf, "Cookie: ");
  1235. for (opt = vpninfo->cookies; opt; opt = opt->next)
  1236. buf_append(buf, "%s=%s%s", opt->option,
  1237. opt->value, opt->next ? "; " : "\r\n");
  1238. }
  1239. }