⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 telnetd.c

📁 经典的unix下telnetd代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif#ifdef	AUTHENTICATION    fprintf(stderr, " [-edebug]");#endif    fprintf(stderr, " [-h]");    fprintf(stderr, " [-L login]");    fprintf(stderr, " [-n]");#ifdef	_CRAY    fprintf(stderr, " [-r[lowpty]-[highpty]]");#endif    fprintf(stderr, "\n\t");#ifdef	HAVE_GETTOSBYNAME    fprintf(stderr, " [-S tos]");#endif#ifdef	AUTHENTICATION    fprintf(stderr, " [-X auth-type] [-y] [-z]");#endif    fprintf(stderr, " [-u utmp_hostname_length] [-U]");    fprintf(stderr, " [port]\n");    exit(1);}/* * getterminaltype * *	Ask the other end to send along its terminal type and speed. * Output is the variable terminaltype filled in. */static unsigned char ttytype_sbbuf[] = {    IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE};intgetterminaltype(char *name, size_t name_sz){    int retval = -1;    settimer(baseline);#ifdef AUTHENTICATION    /*     * Handle the Authentication option before we do anything else.     */    send_do(TELOPT_AUTHENTICATION, 1);    while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))	ttloop();    if (his_state_is_will(TELOPT_AUTHENTICATION)) {	retval = auth_wait(name, name_sz);    }#endif#ifdef ENCRYPTION    send_will(TELOPT_ENCRYPT, 1);    send_do(TELOPT_ENCRYPT, 1);	/* esc@magic.fi */#endif    send_do(TELOPT_TTYPE, 1);    send_do(TELOPT_TSPEED, 1);    send_do(TELOPT_XDISPLOC, 1);    send_do(TELOPT_NEW_ENVIRON, 1);    send_do(TELOPT_OLD_ENVIRON, 1);    while (#ifdef ENCRYPTION	   his_do_dont_is_changing(TELOPT_ENCRYPT) ||#endif	   his_will_wont_is_changing(TELOPT_TTYPE) ||	   his_will_wont_is_changing(TELOPT_TSPEED) ||	   his_will_wont_is_changing(TELOPT_XDISPLOC) ||	   his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||	   his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {	ttloop();    }#ifdef ENCRYPTION    /*     * Wait for the negotiation of what type of encryption we can     * send with.  If autoencrypt is not set, this will just return.     */    if (his_state_is_will(TELOPT_ENCRYPT)) {	encrypt_wait();    }#endif    if (his_state_is_will(TELOPT_TSPEED)) {	static unsigned char sb[] =	{ IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };	telnet_net_write (sb, sizeof sb);	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););    }    if (his_state_is_will(TELOPT_XDISPLOC)) {	static unsigned char sb[] =	{ IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };	telnet_net_write (sb, sizeof sb);	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););    }    if (his_state_is_will(TELOPT_NEW_ENVIRON)) {	static unsigned char sb[] =	{ IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };	telnet_net_write (sb, sizeof sb);	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););    }    else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {	static unsigned char sb[] =	{ IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };	telnet_net_write (sb, sizeof sb);	DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););    }    if (his_state_is_will(TELOPT_TTYPE)) {	telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);	DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,				  sizeof ttytype_sbbuf - 2););    }    if (his_state_is_will(TELOPT_TSPEED)) {	while (sequenceIs(tspeedsubopt, baseline))	    ttloop();    }    if (his_state_is_will(TELOPT_XDISPLOC)) {	while (sequenceIs(xdisplocsubopt, baseline))	    ttloop();    }    if (his_state_is_will(TELOPT_NEW_ENVIRON)) {	while (sequenceIs(environsubopt, baseline))	    ttloop();    }    if (his_state_is_will(TELOPT_OLD_ENVIRON)) {	while (sequenceIs(oenvironsubopt, baseline))	    ttloop();    }    if (his_state_is_will(TELOPT_TTYPE)) {	char first[256], last[256];	while (sequenceIs(ttypesubopt, baseline))	    ttloop();	/*	 * If the other side has already disabled the option, then	 * we have to just go with what we (might) have already gotten.	 */	if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {	    strlcpy(first, terminaltype, sizeof(first));	    for(;;) {		/*		 * Save the unknown name, and request the next name.		 */		strlcpy(last, terminaltype, sizeof(last));		_gettermname();		if (terminaltypeok(terminaltype))		    break;		if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||		    his_state_is_wont(TELOPT_TTYPE)) {		    /*		     * We've hit the end.  If this is the same as		     * the first name, just go with it.		     */		    if (strncmp(first, terminaltype, sizeof(first)) == 0)			break;		    /*		     * Get the terminal name one more time, so that		     * RFC1091 compliant telnets will cycle back to		     * the start of the list.		     */		    _gettermname();		    if (strncmp(first, terminaltype, sizeof(first)) != 0)			strlcpy(terminaltype, first, sizeof(terminaltype));		    break;		}	    }	}    }    return(retval);}  /* end of getterminaltype */void_gettermname(void){    /*     * If the client turned off the option,     * we can't send another request, so we     * just return.     */    if (his_state_is_wont(TELOPT_TTYPE))	return;    settimer(baseline);    telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);    DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,			      sizeof ttytype_sbbuf - 2););    while (sequenceIs(ttypesubopt, baseline))	ttloop();}intterminaltypeok(char *s){    return 1;}char host_name[MAXHOSTNAMELEN];char remote_host_name[MAXHOSTNAMELEN];char remote_utmp_name[MAXHOSTNAMELEN];/* * Get a pty, scan input lines. */static voiddoit(struct sockaddr *who, int who_len){    int level;    int ptynum;    char user_name[256];    int error;    /*     * Find an available pty to use.     */    ourpty = getpty(&ptynum);    if (ourpty < 0)	fatal(net, "All network ports in use");#ifdef _SC_CRAY_SECURE_SYS    /*     *	set ttyp line security label     */    if (secflag) {	char slave_dev[16];	snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum);	if (setdevs(tty_dev, &dv) < 0)	    fatal(net, "cannot set pty security");	snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum);	if (setdevs(slave_dev, &dv) < 0)	    fatal(net, "cannot set tty security");    }#endif	/* _SC_CRAY_SECURE_SYS */    error = getnameinfo (who, who_len,				  remote_host_name,				  sizeof(remote_host_name),				  NULL, 0, 				  registerd_host_only ? NI_NAMEREQD : 0);    if (error)	fatal(net, "Couldn't resolve your address into a host name.\r\n\Please contact your net administrator");    gethostname(host_name, sizeof (host_name));    strlcpy (remote_utmp_name, remote_host_name, sizeof(remote_utmp_name));    /* Only trim if too long (and possible) */    if (strlen(remote_utmp_name) > utmp_len) {	char *domain = strchr(host_name, '.');	char *p = strchr(remote_utmp_name, '.');	if (domain != NULL && p != NULL && (strcmp(p, domain) == 0))	    *p = '\0'; /* remove domain part */    }    /*     * If hostname still doesn't fit utmp, use ipaddr.     */    if (strlen(remote_utmp_name) > utmp_len) {	error = getnameinfo (who, who_len,			     remote_utmp_name,			     sizeof(remote_utmp_name),			     NULL, 0,			     NI_NUMERICHOST);	if (error)	    fatal(net, "Couldn't get numeric address\r\n");    }#ifdef AUTHENTICATION    auth_encrypt_init(host_name, remote_host_name, "TELNETD", 1);#endif    init_env();    /*     * get terminal type.     */    *user_name = 0;    level = getterminaltype(user_name, sizeof(user_name));    esetenv("TERM", terminaltype ? terminaltype : "network", 1);#ifdef _SC_CRAY_SECURE_SYS    if (secflag) {	if (setulvl(dv.dv_actlvl) < 0)	    fatal(net,"cannot setulvl()");	if (setucmp(dv.dv_actcmp) < 0)	    fatal(net, "cannot setucmp()");    }#endif	/* _SC_CRAY_SECURE_SYS */    /* begin server processing */    my_telnet(net, ourpty, remote_host_name, remote_utmp_name,	      level, user_name);    /*NOTREACHED*/}  /* end of doit *//* output contents of /etc/issue.net, or /etc/issue */static voidshow_issue(void){    FILE *f;    char buf[128];    f = fopen("/etc/issue.net", "r");    if(f == NULL)	f = fopen("/etc/issue", "r");    if(f){	while(fgets(buf, sizeof(buf)-2, f)){	    size_t off = strcspn(buf, "\r\n");  		    strlcpy(buf + off, "\r\n", sizeof(buf) - off);	    writenet((unsigned char*)buf, strlen(buf));	}	fclose(f);    }}/* * Main loop.  Select from pty and network, and * hand data to telnet receiver finite state machine. */voidmy_telnet(int f, int p, const char *host, const char *utmp_host,	  int level, char *autoname){    int on = 1;    char *he;    char *IM;    char *buf;    int nfd;    int startslave_called = 0;    time_t timeout;    fd_set *ibits = NULL;    fd_set *obits = NULL;    fd_set *xbits = NULL;    int setsize;    /*     * Initialize the slc mapping table.     */    get_slc_defaults();    /*     * Do some tests where it is desireable to wait for a response.     * Rather than doing them slowly, one at a time, do them all     * at once.     */    if (my_state_is_wont(TELOPT_SGA))	send_will(TELOPT_SGA, 1);    /*     * Is the client side a 4.2 (NOT 4.3) system?  We need to know this     * because 4.2 clients are unable to deal with TCP urgent data.     *     * To find out, we send out a "DO ECHO".  If the remote system     * answers "WILL ECHO" it is probably a 4.2 client, and we note     * that fact ("WILL ECHO" ==> that the client will echo what     * WE, the server, sends it; it does NOT mean that the client will     * echo the terminal input).     */    send_do(TELOPT_ECHO, 1);    /*     * Send along a couple of other options that we wish to negotiate.     */    send_do(TELOPT_NAWS, 1);    send_will(TELOPT_STATUS, 1);    flowmode = 1;		/* default flow control state */    restartany = -1;	/* uninitialized... */    send_do(TELOPT_LFLOW, 1);    /*     * Spin, waiting for a response from the DO ECHO.  However,     * some REALLY DUMB telnets out there might not respond     * to the DO ECHO.  So, we spin looking for NAWS, (most dumb     * telnets so far seem to respond with WONT for a DO that     * they don't understand...) because by the time we get the     * response, it will already have processed the DO ECHO.     * Kludge upon kludge.     */    while (his_will_wont_is_changing(TELOPT_NAWS))	ttloop();    /*     * But...     * The client might have sent a WILL NAWS as part of its     * startup code; if so, we'll be here before we get the     * response to the DO ECHO.  We'll make the assumption     * that any implementation that understands about NAWS     * is a modern enough implementation that it will respond     * to our DO ECHO request; hence we'll do another spin     * waiting for the ECHO option to settle down, which is     * what we wanted to do in the first place...     */    if (his_want_state_is_will(TELOPT_ECHO) &&	his_state_is_will(TELOPT_NAWS)) {	while (his_will_wont_is_changing(TELOPT_ECHO))	    ttloop();    }    /*     * On the off chance that the telnet client is broken and does not     * respond to the DO ECHO we sent, (after all, we did send the     * DO NAWS negotiation after the DO ECHO, and we won't get here     * until a response to the DO NAWS comes back) 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)) {	DIAG(TD_OPTIONS,	     {output_data("td: simulating recv\r\n");	     });	willoption(TELOPT_ECHO);    }    /*     * Finally, to clean things up, we turn on our echo.  This     * will break stupid 4.2 telnets out of local terminal echo.     */    if (my_state_is_wont(TELOPT_ECHO))	send_will(TELOPT_ECHO, 1);#ifdef TIOCPKT#ifdef	STREAMSPTY    if (!really_stream)#endif	/*	 * Turn on packet mode	 */	ioctl(p, TIOCPKT, (char *)&on);#endif    /*     * Call telrcv() once to pick up anything received during     * terminal type negotiation, 4.2/4.3 determination, and     * linemode negotiation.     */    telrcv();    ioctl(f, FIONBIO, (char *)&on);    ioctl(p, FIONBIO, (char *)&on);#if	defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)    setsockopt(net, SOL_SOCKET, SO_OOBINLINE,	       (void *)&on, sizeof on);#endif	/* defined(SO_OOBINLINE) */#ifdef	SIGTSTP    signal(SIGTSTP, SIG_IGN);#endif#ifdef	SIGTTOU    /*     * Ignoring SIGTTOU keeps the kernel from blocking us     * in ttioct() in /sys/tty.c.     */    signal(SIGTTOU, SIG_IGN);#endif    signal(SIGCHLD, cleanup);#ifdef  TIOCNOTTY    {	int t;	t = open(_PATH_TTY, O_RDWR);	if (t >= 0) {	    ioctl(t, TIOCNOTTY, (char *)0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -