telnet.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2002, Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at http://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * $Id$
  22. ***************************************************************************/
  23. #include "setup.h"
  24. #ifndef CURL_DISABLE_TELNET
  25. /* -- WIN32 approved -- */
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdarg.h>
  29. #include <stdlib.h>
  30. #include <ctype.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <errno.h>
  34. #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
  35. #include <winsock2.h>
  36. #include <time.h>
  37. #include <io.h>
  38. #else
  39. #ifdef HAVE_SYS_SOCKET_H
  40. #include <sys/socket.h>
  41. #endif
  42. #include <netinet/in.h>
  43. #include <sys/time.h>
  44. #include <sys/resource.h>
  45. #ifdef HAVE_UNISTD_H
  46. #include <unistd.h>
  47. #endif
  48. #include <netdb.h>
  49. #ifdef HAVE_ARPA_INET_H
  50. #include <arpa/inet.h>
  51. #endif
  52. #ifdef HAVE_NET_IF_H
  53. #include <net/if.h>
  54. #endif
  55. #include <sys/ioctl.h>
  56. #include <signal.h>
  57. #ifdef HAVE_SYS_PARAM_H
  58. #include <sys/param.h>
  59. #endif
  60. #ifdef HAVE_SYS_SELECT_H
  61. #include <sys/select.h>
  62. #endif
  63. #endif
  64. #include "urldata.h"
  65. #include <curl/curl.h>
  66. #include "transfer.h"
  67. #include "sendf.h"
  68. #define _MPRINTF_REPLACE /* use our functions only */
  69. #include <curl/mprintf.h>
  70. #define TELOPTS
  71. #define TELCMDS
  72. #include "arpa_telnet.h"
  73. /* The last #include file should be: */
  74. #ifdef MALLOCDEBUG
  75. #include "memdebug.h"
  76. #endif
  77. #define SUBBUFSIZE 512
  78. #define SB_CLEAR(x) x->subpointer = x->subbuffer;
  79. #define SB_TERM(x) { x->subend = x->subpointer; SB_CLEAR(x); }
  80. #define SB_ACCUM(x,c) if (x->subpointer < (x->subbuffer+sizeof x->subbuffer)) { \
  81. *x->subpointer++ = (c); \
  82. }
  83. #define SB_GET(x) ((*x->subpointer++)&0xff)
  84. #define SB_PEEK(x) ((*x->subpointer)&0xff)
  85. #define SB_EOF(x) (x->subpointer >= x->subend)
  86. #define SB_LEN(x) (x->subend - x->subpointer)
  87. static
  88. void telrcv(struct connectdata *,
  89. unsigned char *inbuf, /* Data received from socket */
  90. int count); /* Number of bytes received */
  91. static void printoption(struct SessionHandle *data,
  92. const char *direction,
  93. int cmd, int option);
  94. static void negotiate(struct connectdata *);
  95. static void send_negotiation(struct connectdata *, int cmd, int option);
  96. static void set_local_option(struct connectdata *, int cmd, int option);
  97. static void set_remote_option(struct connectdata *, int cmd, int option);
  98. static void printsub(struct SessionHandle *data,
  99. int direction, unsigned char *pointer, int length);
  100. static void suboption(struct connectdata *);
  101. /* For negotiation compliant to RFC 1143 */
  102. #define NO 0
  103. #define YES 1
  104. #define WANTYES 2
  105. #define WANTNO 3
  106. #define EMPTY 0
  107. #define OPPOSITE 1
  108. /*
  109. * Telnet receiver states for fsm
  110. */
  111. typedef enum
  112. {
  113. TS_DATA = 0,
  114. TS_IAC,
  115. TS_WILL,
  116. TS_WONT,
  117. TS_DO,
  118. TS_DONT,
  119. TS_CR,
  120. TS_SB, /* sub-option collection */
  121. TS_SE /* looking for sub-option end */
  122. } TelnetReceive;
  123. struct TELNET {
  124. int please_negotiate;
  125. int already_negotiated;
  126. int us[256];
  127. int usq[256];
  128. int us_preferred[256];
  129. int him[256];
  130. int himq[256];
  131. int him_preferred[256];
  132. char subopt_ttype[32]; /* Set with suboption TTYPE */
  133. char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */
  134. struct curl_slist *telnet_vars; /* Environment variables */
  135. /* suboptions */
  136. char subbuffer[SUBBUFSIZE];
  137. char *subpointer, *subend; /* buffer for sub-options */
  138. TelnetReceive telrcv_state;
  139. };
  140. static
  141. CURLcode init_telnet(struct connectdata *conn)
  142. {
  143. struct TELNET *tn;
  144. tn = (struct TELNET *)malloc(sizeof(struct TELNET));
  145. if(!tn)
  146. return CURLE_OUT_OF_MEMORY;
  147. conn->proto.telnet = (void *)tn; /* make us known */
  148. memset(tn, 0, sizeof(struct TELNET));
  149. tn->telrcv_state = TS_DATA;
  150. /* Init suboptions */
  151. SB_CLEAR(tn);
  152. /* Set all options to NO */
  153. #if 0
  154. /* NO is zero => default fill pattern */
  155. memset(tn->us, NO, 256);
  156. memset(tn->usq, NO, 256);
  157. memset(tn->us_preferred, NO, 256);
  158. memset(tn->him, NO, 256);
  159. memset(tn->himq, NO, 256);
  160. memset(tn->him_preferred, NO, 256);
  161. #endif
  162. /* Set the options we want by default */
  163. tn->us_preferred[TELOPT_BINARY] = YES;
  164. tn->us_preferred[TELOPT_SGA] = YES;
  165. tn->him_preferred[TELOPT_BINARY] = YES;
  166. tn->him_preferred[TELOPT_SGA] = YES;
  167. return CURLE_OK;
  168. }
  169. static void negotiate(struct connectdata *conn)
  170. {
  171. int i;
  172. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  173. for(i = 0;i < NTELOPTS;i++)
  174. {
  175. if(tn->us_preferred[i] == YES)
  176. set_local_option(conn, i, YES);
  177. if(tn->him_preferred[i] == YES)
  178. set_remote_option(conn, i, YES);
  179. }
  180. }
  181. static void printoption(struct SessionHandle *data,
  182. const char *direction, int cmd, int option)
  183. {
  184. const char *fmt;
  185. const char *opt;
  186. if (data->set.verbose)
  187. {
  188. if (cmd == IAC)
  189. {
  190. if (TELCMD_OK(option))
  191. Curl_infof(data, "%s IAC %s\n", direction, TELCMD(option));
  192. else
  193. Curl_infof(data, "%s IAC %d\n", direction, option);
  194. }
  195. else
  196. {
  197. fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
  198. (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
  199. if (fmt)
  200. {
  201. if (TELOPT_OK(option))
  202. opt = TELOPT(option);
  203. else if (option == TELOPT_EXOPL)
  204. opt = "EXOPL";
  205. else
  206. opt = NULL;
  207. if(opt)
  208. Curl_infof(data, "%s %s %s\n", direction, fmt, opt);
  209. else
  210. Curl_infof(data, "%s %s %d\n", direction, fmt, option);
  211. }
  212. else
  213. Curl_infof(data, "%s %d %d\n", direction, cmd, option);
  214. }
  215. }
  216. }
  217. static void send_negotiation(struct connectdata *conn, int cmd, int option)
  218. {
  219. unsigned char buf[3];
  220. buf[0] = IAC;
  221. buf[1] = cmd;
  222. buf[2] = option;
  223. swrite(conn->firstsocket, buf, 3);
  224. printoption(conn->data, "SENT", cmd, option);
  225. }
  226. static
  227. void set_remote_option(struct connectdata *conn, int option, int newstate)
  228. {
  229. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  230. if(newstate == YES)
  231. {
  232. switch(tn->him[option])
  233. {
  234. case NO:
  235. tn->him[option] = WANTYES;
  236. send_negotiation(conn, DO, option);
  237. break;
  238. case YES:
  239. /* Already enabled */
  240. break;
  241. case WANTNO:
  242. switch(tn->himq[option])
  243. {
  244. case EMPTY:
  245. /* Already negotiating for YES, queue the request */
  246. tn->himq[option] = OPPOSITE;
  247. break;
  248. case OPPOSITE:
  249. /* Error: already queued an enable request */
  250. break;
  251. }
  252. break;
  253. case WANTYES:
  254. switch(tn->himq[option])
  255. {
  256. case EMPTY:
  257. /* Error: already negotiating for enable */
  258. break;
  259. case OPPOSITE:
  260. tn->himq[option] = EMPTY;
  261. break;
  262. }
  263. break;
  264. }
  265. }
  266. else /* NO */
  267. {
  268. switch(tn->him[option])
  269. {
  270. case NO:
  271. /* Already disabled */
  272. break;
  273. case YES:
  274. tn->him[option] = WANTNO;
  275. send_negotiation(conn, DONT, option);
  276. break;
  277. case WANTNO:
  278. switch(tn->himq[option])
  279. {
  280. case EMPTY:
  281. /* Already negotiating for NO */
  282. break;
  283. case OPPOSITE:
  284. tn->himq[option] = EMPTY;
  285. break;
  286. }
  287. break;
  288. case WANTYES:
  289. switch(tn->himq[option])
  290. {
  291. case EMPTY:
  292. tn->himq[option] = OPPOSITE;
  293. break;
  294. case OPPOSITE:
  295. break;
  296. }
  297. break;
  298. }
  299. }
  300. }
  301. static
  302. void rec_will(struct connectdata *conn, int option)
  303. {
  304. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  305. switch(tn->him[option])
  306. {
  307. case NO:
  308. if(tn->him_preferred[option] == YES)
  309. {
  310. tn->him[option] = YES;
  311. send_negotiation(conn, DO, option);
  312. }
  313. else
  314. {
  315. send_negotiation(conn, DONT, option);
  316. }
  317. break;
  318. case YES:
  319. /* Already enabled */
  320. break;
  321. case WANTNO:
  322. switch(tn->himq[option])
  323. {
  324. case EMPTY:
  325. /* Error: DONT answered by WILL */
  326. tn->him[option] = NO;
  327. break;
  328. case OPPOSITE:
  329. /* Error: DONT answered by WILL */
  330. tn->him[option] = YES;
  331. tn->himq[option] = EMPTY;
  332. break;
  333. }
  334. break;
  335. case WANTYES:
  336. switch(tn->himq[option])
  337. {
  338. case EMPTY:
  339. tn->him[option] = YES;
  340. break;
  341. case OPPOSITE:
  342. tn->him[option] = WANTNO;
  343. tn->himq[option] = EMPTY;
  344. send_negotiation(conn, DONT, option);
  345. break;
  346. }
  347. break;
  348. }
  349. }
  350. static
  351. void rec_wont(struct connectdata *conn, int option)
  352. {
  353. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  354. switch(tn->him[option])
  355. {
  356. case NO:
  357. /* Already disabled */
  358. break;
  359. case YES:
  360. tn->him[option] = NO;
  361. send_negotiation(conn, DONT, option);
  362. break;
  363. case WANTNO:
  364. switch(tn->himq[option])
  365. {
  366. case EMPTY:
  367. tn->him[option] = NO;
  368. break;
  369. case OPPOSITE:
  370. tn->him[option] = WANTYES;
  371. tn->himq[option] = EMPTY;
  372. send_negotiation(conn, DO, option);
  373. break;
  374. }
  375. break;
  376. case WANTYES:
  377. switch(tn->himq[option])
  378. {
  379. case EMPTY:
  380. tn->him[option] = NO;
  381. break;
  382. case OPPOSITE:
  383. tn->him[option] = NO;
  384. tn->himq[option] = EMPTY;
  385. break;
  386. }
  387. break;
  388. }
  389. }
  390. void set_local_option(struct connectdata *conn, int option, int newstate)
  391. {
  392. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  393. if(newstate == YES)
  394. {
  395. switch(tn->us[option])
  396. {
  397. case NO:
  398. tn->us[option] = WANTYES;
  399. send_negotiation(conn, WILL, option);
  400. break;
  401. case YES:
  402. /* Already enabled */
  403. break;
  404. case WANTNO:
  405. switch(tn->usq[option])
  406. {
  407. case EMPTY:
  408. /* Already negotiating for YES, queue the request */
  409. tn->usq[option] = OPPOSITE;
  410. break;
  411. case OPPOSITE:
  412. /* Error: already queued an enable request */
  413. break;
  414. }
  415. break;
  416. case WANTYES:
  417. switch(tn->usq[option])
  418. {
  419. case EMPTY:
  420. /* Error: already negotiating for enable */
  421. break;
  422. case OPPOSITE:
  423. tn->usq[option] = EMPTY;
  424. break;
  425. }
  426. break;
  427. }
  428. }
  429. else /* NO */
  430. {
  431. switch(tn->us[option])
  432. {
  433. case NO:
  434. /* Already disabled */
  435. break;
  436. case YES:
  437. tn->us[option] = WANTNO;
  438. send_negotiation(conn, WONT, option);
  439. break;
  440. case WANTNO:
  441. switch(tn->usq[option])
  442. {
  443. case EMPTY:
  444. /* Already negotiating for NO */
  445. break;
  446. case OPPOSITE:
  447. tn->usq[option] = EMPTY;
  448. break;
  449. }
  450. break;
  451. case WANTYES:
  452. switch(tn->usq[option])
  453. {
  454. case EMPTY:
  455. tn->usq[option] = OPPOSITE;
  456. break;
  457. case OPPOSITE:
  458. break;
  459. }
  460. break;
  461. }
  462. }
  463. }
  464. static
  465. void rec_do(struct connectdata *conn, int option)
  466. {
  467. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  468. switch(tn->us[option])
  469. {
  470. case NO:
  471. if(tn->us_preferred[option] == YES)
  472. {
  473. tn->us[option] = YES;
  474. send_negotiation(conn, WILL, option);
  475. }
  476. else
  477. {
  478. send_negotiation(conn, WONT, option);
  479. }
  480. break;
  481. case YES:
  482. /* Already enabled */
  483. break;
  484. case WANTNO:
  485. switch(tn->usq[option])
  486. {
  487. case EMPTY:
  488. /* Error: DONT answered by WILL */
  489. tn->us[option] = NO;
  490. break;
  491. case OPPOSITE:
  492. /* Error: DONT answered by WILL */
  493. tn->us[option] = YES;
  494. tn->usq[option] = EMPTY;
  495. break;
  496. }
  497. break;
  498. case WANTYES:
  499. switch(tn->usq[option])
  500. {
  501. case EMPTY:
  502. tn->us[option] = YES;
  503. break;
  504. case OPPOSITE:
  505. tn->us[option] = WANTNO;
  506. tn->himq[option] = EMPTY;
  507. send_negotiation(conn, WONT, option);
  508. break;
  509. }
  510. break;
  511. }
  512. }
  513. static
  514. void rec_dont(struct connectdata *conn, int option)
  515. {
  516. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  517. switch(tn->us[option])
  518. {
  519. case NO:
  520. /* Already disabled */
  521. break;
  522. case YES:
  523. tn->us[option] = NO;
  524. send_negotiation(conn, WONT, option);
  525. break;
  526. case WANTNO:
  527. switch(tn->usq[option])
  528. {
  529. case EMPTY:
  530. tn->us[option] = NO;
  531. break;
  532. case OPPOSITE:
  533. tn->us[option] = WANTYES;
  534. tn->usq[option] = EMPTY;
  535. send_negotiation(conn, WILL, option);
  536. break;
  537. }
  538. break;
  539. case WANTYES:
  540. switch(tn->usq[option])
  541. {
  542. case EMPTY:
  543. tn->us[option] = NO;
  544. break;
  545. case OPPOSITE:
  546. tn->us[option] = NO;
  547. tn->usq[option] = EMPTY;
  548. break;
  549. }
  550. break;
  551. }
  552. }
  553. static void printsub(struct SessionHandle *data,
  554. int direction, /* '<' or '>' */
  555. unsigned char *pointer, /* where suboption data is */
  556. int length) /* length of suboption data */
  557. {
  558. int i = 0;
  559. if (data->set.verbose)
  560. {
  561. if (direction)
  562. {
  563. Curl_infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
  564. if (length >= 3)
  565. {
  566. int j;
  567. i = pointer[length-2];
  568. j = pointer[length-1];
  569. if (i != IAC || j != SE)
  570. {
  571. Curl_infof(data, "(terminated by ");
  572. if (TELOPT_OK(i))
  573. Curl_infof(data, "%s ", TELOPT(i));
  574. else if (TELCMD_OK(i))
  575. Curl_infof(data, "%s ", TELCMD(i));
  576. else
  577. Curl_infof(data, "%d ", i);
  578. if (TELOPT_OK(j))
  579. Curl_infof(data, "%s", TELOPT(j));
  580. else if (TELCMD_OK(j))
  581. Curl_infof(data, "%s", TELCMD(j));
  582. else
  583. Curl_infof(data, "%d", j);
  584. Curl_infof(data, ", not IAC SE!) ");
  585. }
  586. }
  587. length -= 2;
  588. }
  589. if (length < 1)
  590. {
  591. Curl_infof(data, "(Empty suboption?)");
  592. return;
  593. }
  594. if (TELOPT_OK(pointer[0])) {
  595. switch(pointer[0]) {
  596. case TELOPT_TTYPE:
  597. case TELOPT_XDISPLOC:
  598. case TELOPT_NEW_ENVIRON:
  599. Curl_infof(data, "%s", TELOPT(pointer[0]));
  600. break;
  601. default:
  602. Curl_infof(data, "%s (unsupported)", TELOPT(pointer[0]));
  603. break;
  604. }
  605. }
  606. else
  607. Curl_infof(data, "%d (unknown)", pointer[i]);
  608. switch(pointer[1]) {
  609. case TELQUAL_IS:
  610. Curl_infof(data, " IS");
  611. break;
  612. case TELQUAL_SEND:
  613. Curl_infof(data, " SEND");
  614. break;
  615. case TELQUAL_INFO:
  616. Curl_infof(data, " INFO/REPLY");
  617. break;
  618. case TELQUAL_NAME:
  619. Curl_infof(data, " NAME");
  620. break;
  621. }
  622. switch(pointer[0]) {
  623. case TELOPT_TTYPE:
  624. case TELOPT_XDISPLOC:
  625. pointer[length] = 0;
  626. Curl_infof(data, " \"%s\"", &pointer[2]);
  627. break;
  628. case TELOPT_NEW_ENVIRON:
  629. if(pointer[1] == TELQUAL_IS) {
  630. Curl_infof(data, " ");
  631. for(i = 3;i < length;i++) {
  632. switch(pointer[i]) {
  633. case NEW_ENV_VAR:
  634. Curl_infof(data, ", ");
  635. break;
  636. case NEW_ENV_VALUE:
  637. Curl_infof(data, " = ");
  638. break;
  639. default:
  640. Curl_infof(data, "%c", pointer[i]);
  641. break;
  642. }
  643. }
  644. }
  645. break;
  646. default:
  647. for (i = 2; i < length; i++)
  648. Curl_infof(data, " %.2x", pointer[i]);
  649. break;
  650. }
  651. if (direction)
  652. {
  653. Curl_infof(data, "\n");
  654. }
  655. }
  656. }
  657. static int check_telnet_options(struct connectdata *conn)
  658. {
  659. struct curl_slist *head;
  660. char option_keyword[128];
  661. char option_arg[256];
  662. char *buf;
  663. struct SessionHandle *data = conn->data;
  664. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  665. /* Add the user name as an environment variable if it
  666. was given on the command line */
  667. if(conn->bits.user_passwd)
  668. {
  669. char *buf = malloc(256);
  670. sprintf(buf, "USER,%s", data->state.user);
  671. tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
  672. tn->us_preferred[TELOPT_NEW_ENVIRON] = YES;
  673. }
  674. for(head = data->set.telnet_options; head; head=head->next) {
  675. if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
  676. option_keyword, option_arg) == 2) {
  677. /* Terminal type */
  678. if(strequal(option_keyword, "TTYPE")) {
  679. strncpy(tn->subopt_ttype, option_arg, 31);
  680. tn->subopt_ttype[31] = 0; /* String termination */
  681. tn->us_preferred[TELOPT_TTYPE] = YES;
  682. continue;
  683. }
  684. /* Display variable */
  685. if(strequal(option_keyword, "XDISPLOC")) {
  686. strncpy(tn->subopt_xdisploc, option_arg, 127);
  687. tn->subopt_xdisploc[127] = 0; /* String termination */
  688. tn->us_preferred[TELOPT_XDISPLOC] = YES;
  689. continue;
  690. }
  691. /* Environment variable */
  692. if(strequal(option_keyword, "NEW_ENV")) {
  693. buf = strdup(option_arg);
  694. if(!buf)
  695. return CURLE_OUT_OF_MEMORY;
  696. tn->telnet_vars = curl_slist_append(tn->telnet_vars, buf);
  697. tn->us_preferred[TELOPT_NEW_ENVIRON] = YES;
  698. continue;
  699. }
  700. failf(data, "Unknown telnet option %s", head->data);
  701. return CURLE_UNKNOWN_TELNET_OPTION;
  702. } else {
  703. failf(data, "Syntax error in telnet option: %s", head->data);
  704. return CURLE_TELNET_OPTION_SYNTAX;
  705. }
  706. }
  707. return CURLE_OK;
  708. }
  709. /*
  710. * suboption()
  711. *
  712. * Look at the sub-option buffer, and try to be helpful to the other
  713. * side.
  714. */
  715. static void suboption(struct connectdata *conn)
  716. {
  717. struct curl_slist *v;
  718. unsigned char subchar;
  719. unsigned char temp[2048];
  720. int len;
  721. int tmplen;
  722. char varname[128];
  723. char varval[128];
  724. struct SessionHandle *data = conn->data;
  725. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  726. printsub(data, '<', (unsigned char *)tn->subbuffer, SB_LEN(tn)+2);
  727. switch (subchar = SB_GET(tn)) {
  728. case TELOPT_TTYPE:
  729. len = strlen(tn->subopt_ttype) + 4 + 2;
  730. snprintf((char *)temp, sizeof(temp),
  731. "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
  732. TELQUAL_IS, tn->subopt_ttype, IAC, SE);
  733. swrite(conn->firstsocket, temp, len);
  734. printsub(data, '>', &temp[2], len-2);
  735. break;
  736. case TELOPT_XDISPLOC:
  737. len = strlen(tn->subopt_xdisploc) + 4 + 2;
  738. snprintf((char *)temp, sizeof(temp),
  739. "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
  740. TELQUAL_IS, tn->subopt_xdisploc, IAC, SE);
  741. swrite(conn->firstsocket, temp, len);
  742. printsub(data, '>', &temp[2], len-2);
  743. break;
  744. case TELOPT_NEW_ENVIRON:
  745. snprintf((char *)temp, sizeof(temp),
  746. "%c%c%c%c", IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS);
  747. len = 4;
  748. for(v = tn->telnet_vars;v;v = v->next) {
  749. tmplen = (strlen(v->data) + 1);
  750. /* Add the variable only if it fits */
  751. if(len + tmplen < (int)sizeof(temp)-6) {
  752. sscanf(v->data, "%127[^,],%s", varname, varval);
  753. snprintf((char *)&temp[len], sizeof(temp) - len,
  754. "%c%s%c%s", NEW_ENV_VAR, varname,
  755. NEW_ENV_VALUE, varval);
  756. len += tmplen;
  757. }
  758. }
  759. snprintf((char *)&temp[len], sizeof(temp) - len,
  760. "%c%c", IAC, SE);
  761. len += 2;
  762. swrite(conn->firstsocket, temp, len);
  763. printsub(data, '>', &temp[2], len-2);
  764. break;
  765. }
  766. return;
  767. }
  768. static
  769. void telrcv(struct connectdata *conn,
  770. unsigned char *inbuf, /* Data received from socket */
  771. int count) /* Number of bytes received */
  772. {
  773. unsigned char c;
  774. int index = 0;
  775. struct SessionHandle *data = conn->data;
  776. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  777. while(count--)
  778. {
  779. c = inbuf[index++];
  780. switch (tn->telrcv_state)
  781. {
  782. case TS_CR:
  783. tn->telrcv_state = TS_DATA;
  784. if (c == '\0')
  785. {
  786. break; /* Ignore \0 after CR */
  787. }
  788. Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
  789. continue;
  790. case TS_DATA:
  791. if (c == IAC)
  792. {
  793. tn->telrcv_state = TS_IAC;
  794. break;
  795. }
  796. else if(c == '\r')
  797. {
  798. tn->telrcv_state = TS_CR;
  799. }
  800. Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
  801. continue;
  802. case TS_IAC:
  803. process_iac:
  804. switch (c)
  805. {
  806. case WILL:
  807. tn->telrcv_state = TS_WILL;
  808. continue;
  809. case WONT:
  810. tn->telrcv_state = TS_WONT;
  811. continue;
  812. case DO:
  813. tn->telrcv_state = TS_DO;
  814. continue;
  815. case DONT:
  816. tn->telrcv_state = TS_DONT;
  817. continue;
  818. case SB:
  819. SB_CLEAR(tn);
  820. tn->telrcv_state = TS_SB;
  821. continue;
  822. case IAC:
  823. Curl_client_write(data, CLIENTWRITE_BODY, (char *)&c, 1);
  824. break;
  825. case DM:
  826. case NOP:
  827. case GA:
  828. default:
  829. printoption(data, "RCVD", IAC, c);
  830. break;
  831. }
  832. tn->telrcv_state = TS_DATA;
  833. continue;
  834. case TS_WILL:
  835. printoption(data, "RCVD", WILL, c);
  836. tn->please_negotiate = 1;
  837. rec_will(conn, c);
  838. tn->telrcv_state = TS_DATA;
  839. continue;
  840. case TS_WONT:
  841. printoption(data, "RCVD", WONT, c);
  842. tn->please_negotiate = 1;
  843. rec_wont(conn, c);
  844. tn->telrcv_state = TS_DATA;
  845. continue;
  846. case TS_DO:
  847. printoption(data, "RCVD", DO, c);
  848. tn->please_negotiate = 1;
  849. rec_do(conn, c);
  850. tn->telrcv_state = TS_DATA;
  851. continue;
  852. case TS_DONT:
  853. printoption(data, "RCVD", DONT, c);
  854. tn->please_negotiate = 1;
  855. rec_dont(conn, c);
  856. tn->telrcv_state = TS_DATA;
  857. continue;
  858. case TS_SB:
  859. if (c == IAC)
  860. {
  861. tn->telrcv_state = TS_SE;
  862. }
  863. else
  864. {
  865. SB_ACCUM(tn,c);
  866. }
  867. continue;
  868. case TS_SE:
  869. if (c != SE)
  870. {
  871. if (c != IAC)
  872. {
  873. /*
  874. * This is an error. We only expect to get
  875. * "IAC IAC" or "IAC SE". Several things may
  876. * have happend. An IAC was not doubled, the
  877. * IAC SE was left off, or another option got
  878. * inserted into the suboption are all possibilities.
  879. * If we assume that the IAC was not doubled,
  880. * and really the IAC SE was left off, we could
  881. * get into an infinate loop here. So, instead,
  882. * we terminate the suboption, and process the
  883. * partial suboption if we can.
  884. */
  885. SB_ACCUM(tn, (unsigned char)IAC);
  886. SB_ACCUM(tn, c);
  887. tn->subpointer -= 2;
  888. SB_TERM(tn);
  889. printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
  890. suboption(conn); /* handle sub-option */
  891. tn->telrcv_state = TS_IAC;
  892. goto process_iac;
  893. }
  894. SB_ACCUM(tn,c);
  895. tn->telrcv_state = TS_SB;
  896. }
  897. else
  898. {
  899. SB_ACCUM(tn, (unsigned char)IAC);
  900. SB_ACCUM(tn, (unsigned char)SE);
  901. tn->subpointer -= 2;
  902. SB_TERM(tn);
  903. suboption(conn); /* handle sub-option */
  904. tn->telrcv_state = TS_DATA;
  905. }
  906. break;
  907. }
  908. }
  909. }
  910. CURLcode Curl_telnet_done(struct connectdata *conn)
  911. {
  912. struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  913. curl_slist_free_all(tn->telnet_vars);
  914. free(conn->proto.telnet);
  915. conn->proto.telnet = NULL;
  916. return CURLE_OK;
  917. }
  918. CURLcode Curl_telnet(struct connectdata *conn)
  919. {
  920. CURLcode code;
  921. struct SessionHandle *data = conn->data;
  922. int sockfd = conn->firstsocket;
  923. #ifdef WIN32
  924. WSAEVENT event_handle;
  925. WSANETWORKEVENTS events;
  926. HANDLE stdin_handle;
  927. HANDLE objs[2];
  928. DWORD waitret;
  929. #else
  930. fd_set readfd;
  931. fd_set keepfd;
  932. #endif
  933. bool keepon = TRUE;
  934. char *buf = data->state.buffer;
  935. ssize_t nread;
  936. struct TELNET *tn;
  937. struct timeval now; /* current time */
  938. code = init_telnet(conn);
  939. if(code)
  940. return code;
  941. tn = (struct TELNET *)conn->proto.telnet;
  942. code = check_telnet_options(conn);
  943. if(code)
  944. return code;
  945. #ifdef WIN32
  946. /* We want to wait for both stdin and the socket. Since
  947. ** the select() function in winsock only works on sockets
  948. ** we have to use the WaitForMultipleObjects() call.
  949. */
  950. /* First, create a sockets event object */
  951. event_handle = WSACreateEvent();
  952. /* The get the Windows file handle for stdin */
  953. stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
  954. /* Create the list of objects to wait for */
  955. objs[0] = stdin_handle;
  956. objs[1] = event_handle;
  957. /* Tell winsock what events we want to listen to */
  958. if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
  959. return 0;
  960. }
  961. /* Keep on listening and act on events */
  962. while(keepon) {
  963. waitret = WaitForMultipleObjects(2, objs, FALSE, INFINITE);
  964. switch(waitret - WAIT_OBJECT_0)
  965. {
  966. case 0:
  967. {
  968. unsigned char outbuf[2];
  969. int out_count = 0;
  970. ssize_t bytes_written;
  971. char *buffer = buf;
  972. if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) {
  973. keepon = FALSE;
  974. break;
  975. }
  976. while(nread--) {
  977. outbuf[0] = *buffer++;
  978. out_count = 1;
  979. if(outbuf[0] == IAC)
  980. outbuf[out_count++] = IAC;
  981. Curl_write(conn, conn->firstsocket, outbuf,
  982. out_count, &bytes_written);
  983. }
  984. }
  985. break;
  986. case 1:
  987. if(WSAEnumNetworkEvents(sockfd, event_handle, &events)
  988. != SOCKET_ERROR)
  989. {
  990. if(events.lNetworkEvents & FD_READ)
  991. {
  992. /* This reallu OUGHT to check its return code. */
  993. Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
  994. telrcv(conn, (unsigned char *)buf, nread);
  995. fflush(stdout);
  996. /* Negotiate if the peer has started negotiating,
  997. otherwise don't. We don't want to speak telnet with
  998. non-telnet servers, like POP or SMTP. */
  999. if(tn->please_negotiate && !tn->already_negotiated) {
  1000. negotiate(conn);
  1001. tn->already_negotiated = 1;
  1002. }
  1003. }
  1004. if(events.lNetworkEvents & FD_CLOSE)
  1005. {
  1006. keepon = FALSE;
  1007. }
  1008. }
  1009. break;
  1010. }
  1011. }
  1012. #else
  1013. FD_ZERO (&readfd); /* clear it */
  1014. FD_SET (sockfd, &readfd);
  1015. FD_SET (0, &readfd);
  1016. keepfd = readfd;
  1017. while (keepon) {
  1018. struct timeval interval;
  1019. readfd = keepfd; /* set this every lap in the loop */
  1020. interval.tv_sec = 1;
  1021. interval.tv_usec = 0;
  1022. switch (select (sockfd + 1, &readfd, NULL, NULL, &interval)) {
  1023. case -1: /* error, stop reading */
  1024. keepon = FALSE;
  1025. continue;
  1026. case 0: /* timeout */
  1027. break;
  1028. default: /* read! */
  1029. if(FD_ISSET(0, &readfd)) { /* read from stdin */
  1030. unsigned char outbuf[2];
  1031. int out_count = 0;
  1032. ssize_t bytes_written;
  1033. char *buffer = buf;
  1034. nread = read(0, buf, 255);
  1035. while(nread--) {
  1036. outbuf[0] = *buffer++;
  1037. out_count = 1;
  1038. if(outbuf[0] == IAC)
  1039. outbuf[out_count++] = IAC;
  1040. Curl_write(conn, conn->firstsocket, outbuf,
  1041. out_count, &bytes_written);
  1042. }
  1043. }
  1044. if(FD_ISSET(sockfd, &readfd)) {
  1045. /* This OUGHT to check the return code... */
  1046. Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
  1047. /* if we receive 0 or less here, the server closed the connection and
  1048. we bail out from this! */
  1049. if (nread <= 0) {
  1050. keepon = FALSE;
  1051. break;
  1052. }
  1053. telrcv(conn, (unsigned char *)buf, nread);
  1054. /* Negotiate if the peer has started negotiating,
  1055. otherwise don't. We don't want to speak telnet with
  1056. non-telnet servers, like POP or SMTP. */
  1057. if(tn->please_negotiate && !tn->already_negotiated) {
  1058. negotiate(conn);
  1059. tn->already_negotiated = 1;
  1060. }
  1061. }
  1062. }
  1063. if(data->set.timeout) {
  1064. now = Curl_tvnow();
  1065. if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout) {
  1066. failf(data, "Time-out");
  1067. code = CURLE_OPERATION_TIMEOUTED;
  1068. keepon = FALSE;
  1069. }
  1070. }
  1071. }
  1072. #endif
  1073. /* mark this as "no further transfer wanted" */
  1074. Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
  1075. return code;
  1076. }
  1077. /*
  1078. * local variables:
  1079. * eval: (load-file "../curl-mode.el")
  1080. * end:
  1081. * vim600: fdm=marker
  1082. * vim: et sw=2 ts=2 sts=2 tw=78
  1083. */
  1084. #endif