📄 telnetd.c
字号:
syslog (LOG_AUTH|LOG_NOTICE, "Can't resolve %s: %s", inet_ntoa (saddr.sin_addr), hstrerror (h_errno)); fatal (fd, "Cannot resolve address."); } remote_hostname = xstrdup (hp->h_name); hp = gethostbyname (remote_hostname); if (!hp) { syslog (LOG_AUTH|LOG_NOTICE, "Forward resolve of %s failed: %s", remote_hostname, hstrerror (h_errno)); fatal (fd, "Cannot resolve address."); } for (ap = hp->h_addr_list; *ap; ap++) if (*(ip_addr_t*)ap == saddr.sin_addr.s_addr) break; if (ap == NULL) { syslog (LOG_AUTH|LOG_NOTICE, "None of addresses of %s matched %s", remote_hostname, inet_ntoa (saddr.sin_addr)); exit (0); } } else { if (hp) remote_hostname = xstrdup (hp->h_name); else remote_hostname = xstrdup (inet_ntoa (saddr.sin_addr)); }#endif /* Set socket options */ if (keepalive && setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&true, sizeof (true)) < 0) syslog (LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); if (debug_tcp && setsockopt (fd, SOL_SOCKET, SO_DEBUG, (char *)&true, sizeof (true)) < 0) syslog (LOG_WARNING, "setsockopt (SO_DEBUG): %m"); net = fd; local_hostname = localhost ();#if defined(AUTHENTICATION) || defined(ENCRYPTION) auth_encrypt_init (remote_hostname, local_hostname, "TELNETD", 1);#endif io_setup (); /* get terminal type. */ uname[0] = 0; level = getterminaltype (uname); setenv ("TERM", terminaltype ? terminaltype : "network", 1); if (uname[0]) user_name = xstrdup (uname); pty = startslave (remote_hostname, level, user_name);#ifndef HAVE_STREAMSPTY /* Turn on packet mode */ ioctl (pty, TIOCPKT, (char *)&true);#endif ioctl (pty, FIONBIO, (char *)&true); ioctl (net, FIONBIO, (char *)&true); #if defined(SO_OOBINLINE) setsockopt (net, SOL_SOCKET, SO_OOBINLINE, (char *)&true, sizeof true);#endif #ifdef SIGTSTP signal (SIGTSTP, SIG_IGN);#endif#ifdef SIGTTOU signal (SIGTTOU, SIG_IGN);#endif signal (SIGCHLD, cleanup);}inttelnetd_run (){ int nfd; get_slc_defaults (); if (my_state_is_wont(TELOPT_SGA)) send_will(TELOPT_SGA, 1); /* Old BSD 4.2 clients are unable to deal with TCP out-of-band data. To find out, we send out a "DO ECHO". If the remote side is a BSD 4.2 it will answer "WILL ECHO". See the response processing below. */ send_do(TELOPT_ECHO, 1); if (his_state_is_wont (TELOPT_LINEMODE)) { /* Query the peer for linemode support by trying to negotiate the linemode option. */ linemode = 0; editmode = 0; send_do(TELOPT_LINEMODE, 1); /* send do linemode */ } send_do (TELOPT_NAWS, 1); send_will (TELOPT_STATUS, 1); flowmode = 1; /* default flow control state */ restartany = -1; /* uninitialized... */ send_do (TELOPT_LFLOW, 1); /* Wait for a response from the DO ECHO. Reportedly, some broken clients might not respond to it. To work around this, we wait for a response to NAWS, which should have been processed after DO ECHO (most dumb telnets respond with WONT for a DO that they don't understand). On the other hand, the client might have sent WILL NAWS as part of its startup code, in this case it surely should have answered our DO ECHO, so the second loop is waiting for the ECHO to settle down. */ ttloop (his_will_wont_is_changing (TELOPT_NAWS)); if (his_want_state_is_will (TELOPT_ECHO) && his_state_is_will (TELOPT_NAWS)) ttloop (his_will_wont_is_changing (TELOPT_ECHO)); /* If the remote client is badly broken and did not respond to our DO ECHO, we simulate the receipt of a will echo. This will also send a WONT ECHO to the client, since we assume that the client failed to respond because it believes that it is already in DO ECHO mode, which we do not want. */ if (his_want_state_is_will (TELOPT_ECHO)) { DEBUG(debug_options, 1, debug_output_data ("td: simulating recv\r\n")); willoption (TELOPT_ECHO); } /* Turn on our echo */ if (my_state_is_wont (TELOPT_ECHO)) send_will (TELOPT_ECHO, 1); /* Continuing line mode support. If client does not support real linemode, attempt to negotiate kludge linemode by sending the do timing mark sequence. */ if (lmodetype < REAL_LINEMODE) send_do (TELOPT_TM, 1); /* Pick up anything received during the negotiations */ telrcv (); if (hostinfo) print_hostinfo (); init_termbuf (); localstat (); DEBUG(debug_report, 1, debug_output_data ("td: Entering processing loop\r\n")); nfd = ((net > pty) ? net : pty) + 1; for (;;) { fd_set ibits, obits, xbits; register int c; if (net_input_level () < 0 && pty_input_level () < 0) break; FD_ZERO(&ibits); FD_ZERO(&obits); FD_ZERO(&xbits); /* Never look for input if there's still stuff in the corresponding output buffer */ if (net_output_level () || pty_input_level () > 0) FD_SET (net, &obits); else FD_SET(pty, &ibits); if (pty_output_level () || net_input_level () > 0) FD_SET(pty, &obits); else FD_SET(net, &ibits); if (!SYNCHing) FD_SET(net, &xbits); if ((c = select (nfd, &ibits, &obits, &xbits, NULL)) <= 0) { if (c == -1 && errno == EINTR) continue; sleep(5); continue; } if (FD_ISSET(net, &xbits)) SYNCHing = 1; if (FD_ISSET(net, &ibits)) { /* Something to read from the network... */ /*FIXME: handle !defined(SO_OOBINLINE) */ net_read (); } if (FD_ISSET(pty, &ibits)) { /* Something to read from the pty... */ if (pty_read () < 0) break; c = pty_get_char (1); #if defined(TIOCPKT_IOCTL) if (c & TIOCPKT_IOCTL) { pty_get_char (0); copy_termbuf (); localstat (); }#endif if (c & TIOCPKT_FLUSHWRITE) { static char flushdata[] = { IAC, DM }; pty_get_char (0); netclear(); /* clear buffer back */ net_output_datalen (flushdata, sizeof (flushdata)); set_neturg (); DEBUG(debug_options, 1, printoption("td: send IAC", DM)); } if (his_state_is_will(TELOPT_LFLOW) && (c & (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { int newflow = c & TIOCPKT_DOSTOP ? 1 : 0; if (newflow != flowmode) { net_output_data ("%c%c%c%c%c%c", IAC, SB, TELOPT_LFLOW, flowmode ? LFLOW_ON : LFLOW_OFF, IAC, SE); } pty_get_char (0); } } while (pty_input_level () > 0) { if (net_buffer_is_full ()) break; c = pty_get_char (0); if (c == IAC) net_output_byte (c); net_output_byte (c); if (c == '\r' && my_state_is_wont (TELOPT_BINARY)) { if (pty_input_level () > 0 && pty_get_char (1) == '\n') net_output_byte (pty_get_char (0)); else net_output_byte (0); } } if (FD_ISSET(net, &obits) && net_output_level () > 0) netflush (); if (net_input_level () > 0) telrcv (); if (FD_ISSET(pty, &obits) && pty_output_level () > 0) ptyflush (); } cleanup (0);}voidprint_hostinfo (){ char *im = NULL; char *str;#ifdef HAVE_UNAME struct utsname u; if (uname (&u) == 0) { im = malloc (strlen (UNAME_IM_PREFIX) + strlen (u.sysname) + 1 + strlen (u.release) + strlen (UNAME_IM_SUFFIX) + 1); if (im) sprintf (im, "%s%s %s%s", UNAME_IM_PREFIX, u.sysname, u.release, UNAME_IM_SUFFIX); }#endif /* HAVE_UNAME */ if (!im) im = xstrdup ("\r\n\nUNIX (%l) (%t)\r\n\n"); str = expand_line (im); free (im); DEBUG(debug_pty_data, 1, debug_output_data ("sending %s", str)); pty_input_putback (str, strlen (str)); free (str);}voidtelnetd_version (){ printf ("telnetd - %s %s\n", PACKAGE_NAME, PACKAGE_VERSION); printf ("Copyright (C) 1998,2001,2002 Free Software Foundation, Inc.\n"); printf ("%s comes with ABSOLUTELY NO WARRANTY.\n", PACKAGE_NAME); printf ("You may redistribute copies of %s\n", PACKAGE_NAME); printf ("under the terms of the GNU General Public License.\n"); printf ("For more information about these matters, "); printf ("see the files named COPYING.\n");}voidtelnetd_license (){ static char license_text[] =" This program is free software; you can redistribute it and/or modify\n"" it under the terms of the GNU General Public License as published by\n"" the Free Software Foundation; either version 2, or (at your option)\n"" any later version.\n""\n"" This program is distributed in the hope that it will be useful,\n"" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"" GNU General Public License for more details.\n""\n"" You should have received a copy of the GNU General Public License\n"" along with this program; if not, write to the Free Software\n"" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"; printf ("%s", license_text);}voidtelnetd_help (){ printf ("\Usage: telnetd [OPTION]\n\\n\Options are:\n\ -a, --authmode AUTHMODE specify what mode to use for authentication\n\ -D, --debug[=LEVEL] set debugging level\n\ -E, --exec-login STRING set program to be executed instead of /bin/login\n\ -h, --no-hostinfo do not print host information before login has\n\ been completed\n\ -l, --linemode[=MODE] set line mode\n\ -n, --no-keepalive disable TCP keep-alives\n\ -U, --reverse-lookup refuse connections from addresses that\n\ cannot be mapped back into a symbolic name\n\ -X, --disable-auth-type AUTHTYPE\n\ disable the use of given authentication option\n\Informational options:\n\ -V, --version display this help and exit\n\ -L, --license display license and exit\n\ -H. --help output version information and exit\n");}intstop(){ int volatile _s=1; while (_s) _s=_s; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -