telnet.c 30 KB

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