telnet.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238
  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++ = (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. 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. (void) now;
  946. code = init_telnet(conn);
  947. if(code)
  948. return code;
  949. tn = (struct TELNET *)conn->proto.telnet;
  950. code = check_telnet_options(conn);
  951. if(code)
  952. return code;
  953. #ifdef WIN32
  954. /* We want to wait for both stdin and the socket. Since
  955. ** the select() function in winsock only works on sockets
  956. ** we have to use the WaitForMultipleObjects() call.
  957. */
  958. /* First, create a sockets event object */
  959. event_handle = WSACreateEvent();
  960. /* The get the Windows file handle for stdin */
  961. stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
  962. /* Create the list of objects to wait for */
  963. objs[0] = stdin_handle;
  964. objs[1] = event_handle;
  965. /* Tell winsock what events we want to listen to */
  966. if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
  967. return 0;
  968. }
  969. /* Keep on listening and act on events */
  970. while(keepon) {
  971. waitret = WaitForMultipleObjects(2, objs, FALSE, INFINITE);
  972. switch(waitret - WAIT_OBJECT_0)
  973. {
  974. case 0:
  975. {
  976. unsigned char outbuf[2];
  977. int out_count = 0;
  978. ssize_t bytes_written;
  979. char *buffer = buf;
  980. if(!ReadFile(stdin_handle, buf, 255, &(DWORD)nread, NULL)) {
  981. keepon = FALSE;
  982. break;
  983. }
  984. while(nread--) {
  985. outbuf[0] = *buffer++;
  986. out_count = 1;
  987. if(outbuf[0] == IAC)
  988. outbuf[out_count++] = IAC;
  989. Curl_write(conn, conn->firstsocket, outbuf,
  990. out_count, &bytes_written);
  991. }
  992. }
  993. break;
  994. case 1:
  995. if(WSAEnumNetworkEvents(sockfd, event_handle, &events)
  996. != SOCKET_ERROR)
  997. {
  998. if(events.lNetworkEvents & FD_READ)
  999. {
  1000. /* This reallu OUGHT to check its return code. */
  1001. Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
  1002. telrcv(conn, (unsigned char *)buf, nread);
  1003. fflush(stdout);
  1004. /* Negotiate if the peer has started negotiating,
  1005. otherwise don't. We don't want to speak telnet with
  1006. non-telnet servers, like POP or SMTP. */
  1007. if(tn->please_negotiate && !tn->already_negotiated) {
  1008. negotiate(conn);
  1009. tn->already_negotiated = 1;
  1010. }
  1011. }
  1012. if(events.lNetworkEvents & FD_CLOSE)
  1013. {
  1014. keepon = FALSE;
  1015. }
  1016. }
  1017. break;
  1018. }
  1019. }
  1020. #else
  1021. FD_ZERO (&readfd); /* clear it */
  1022. FD_SET (sockfd, &readfd);
  1023. FD_SET (0, &readfd);
  1024. keepfd = readfd;
  1025. while (keepon) {
  1026. struct timeval interval;
  1027. readfd = keepfd; /* set this every lap in the loop */
  1028. interval.tv_sec = 1;
  1029. interval.tv_usec = 0;
  1030. switch (select (sockfd + 1, &readfd, NULL, NULL, &interval)) {
  1031. case -1: /* error, stop reading */
  1032. keepon = FALSE;
  1033. continue;
  1034. case 0: /* timeout */
  1035. break;
  1036. default: /* read! */
  1037. if(FD_ISSET(0, &readfd)) { /* read from stdin */
  1038. unsigned char outbuf[2];
  1039. int out_count = 0;
  1040. ssize_t bytes_written;
  1041. char *buffer = buf;
  1042. nread = read(0, buf, 255);
  1043. while(nread--) {
  1044. outbuf[0] = *buffer++;
  1045. out_count = 1;
  1046. if(outbuf[0] == IAC)
  1047. outbuf[out_count++] = IAC;
  1048. Curl_write(conn, conn->firstsocket, outbuf,
  1049. out_count, &bytes_written);
  1050. }
  1051. }
  1052. if(FD_ISSET(sockfd, &readfd)) {
  1053. /* This OUGHT to check the return code... */
  1054. Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
  1055. /* if we receive 0 or less here, the server closed the connection and
  1056. we bail out from this! */
  1057. if (nread <= 0) {
  1058. keepon = FALSE;
  1059. break;
  1060. }
  1061. telrcv(conn, (unsigned char *)buf, nread);
  1062. /* Negotiate if the peer has started negotiating,
  1063. otherwise don't. We don't want to speak telnet with
  1064. non-telnet servers, like POP or SMTP. */
  1065. if(tn->please_negotiate && !tn->already_negotiated) {
  1066. negotiate(conn);
  1067. tn->already_negotiated = 1;
  1068. }
  1069. }
  1070. }
  1071. if(data->set.timeout) {
  1072. now = Curl_tvnow();
  1073. if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout) {
  1074. failf(data, "Time-out");
  1075. code = CURLE_OPERATION_TIMEOUTED;
  1076. keepon = FALSE;
  1077. }
  1078. }
  1079. }
  1080. #endif
  1081. /* mark this as "no further transfer wanted" */
  1082. Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
  1083. return code;
  1084. }
  1085. /*
  1086. * local variables:
  1087. * eval: (load-file "../curl-mode.el")
  1088. * end:
  1089. * vim600: fdm=marker
  1090. * vim: et sw=2 ts=2 sts=2 tw=78
  1091. */
  1092. #endif