telnet.c 29 KB

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