telnet.c 34 KB

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