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

📄 telnetd.c

📁 这是关于远程登陆TELNET 的源代码 已经测试过的。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */char copyright[] =  "@(#) Copyright (c) 1989 Regents of the University of California.\n"  "All rights reserved.\n";/* * From: @(#)telnetd.c	5.48 (Berkeley) 3/1/91 */char telnetd_rcsid[] =   "$Id: telnetd.c,v 1.24 2000/04/12 21:36:12 dholland Exp $";#include "../version.h"#include <netdb.h>#include <termcap.h>#include <netinet/in.h>/* #include <netinet/ip.h> */ /* Don't think this is used at all here */#include <arpa/inet.h>#include <assert.h>#include "telnetd.h"#include "pathnames.h"#include "setproctitle.h"#if	defined(AUTHENTICATE)#include <libtelnet/auth.h>#include <libtelnet/auth-proto.h>#include <libtelnet/misc-proto.h>int	auth_level = 0;#endif#if	defined(SecurID)int	require_SecurID = 0;#endif/* In Linux, this is an enum */#if defined(__linux__) || defined(IPPROTO_IP)#define HAS_IPPROTO_IP#endifstatic void doit(struct sockaddr_in *who);static int terminaltypeok(const char *s);/* * I/O data buffers, * pointers, and counters. */char	ptyibuf[BUFSIZ], *ptyip = ptyibuf;char	ptyibuf2[BUFSIZ];int	hostinfo = 1;			/* do we print login banner? */int debug = 0;int keepalive = 1;char *loginprg = _PATH_LOGIN;char *progname;extern void usage(void);intmain(int argc, char *argv[], char *env[]){	struct sockaddr_in from;	int on = 1;	socklen_t fromlen;	register int ch;#if	defined(HAS_IPPROTO_IP) && defined(IP_TOS)	int tos = -1;#endif	initsetproctitle(argc, argv, env);	pfrontp = pbackp = ptyobuf;	netip = netibuf;	nfrontp = nbackp = netobuf;#if	defined(ENCRYPT)	nclearto = 0;#endif	progname = *argv;	while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:")) != EOF) {		switch(ch) {#ifdef	AUTHENTICATE		case 'a':			/*			 * Check for required authentication level			 */			if (strcmp(optarg, "debug") == 0) {				extern int auth_debug_mode;				auth_debug_mode = 1;			} else if (strcasecmp(optarg, "none") == 0) {				auth_level = 0;			} else if (strcasecmp(optarg, "other") == 0) {				auth_level = AUTH_OTHER;			} else if (strcasecmp(optarg, "user") == 0) {				auth_level = AUTH_USER;			} else if (strcasecmp(optarg, "valid") == 0) {				auth_level = AUTH_VALID;			} else if (strcasecmp(optarg, "off") == 0) {				/*				 * This hack turns off authentication				 */				auth_level = -1;			} else {				fprintf(stderr,			    "telnetd: unknown authorization level for -a\n");			}			break;#endif	/* AUTHENTICATE */#ifdef BFTPDAEMON		case 'B':			bftpd++;			break;#endif /* BFTPDAEMON */		case 'd':			if (strcmp(optarg, "ebug") == 0) {				debug++;				break;			}			usage();			/* NOTREACHED */			break;#ifdef DIAGNOSTICS		case 'D':			/*			 * Check for desired diagnostics capabilities.			 */			if (!strcmp(optarg, "report")) {				diagnostic |= TD_REPORT|TD_OPTIONS;			} else if (!strcmp(optarg, "exercise")) {				diagnostic |= TD_EXERCISE;			} else if (!strcmp(optarg, "netdata")) {				diagnostic |= TD_NETDATA;			} else if (!strcmp(optarg, "ptydata")) {				diagnostic |= TD_PTYDATA;			} else if (!strcmp(optarg, "options")) {				diagnostic |= TD_OPTIONS;			} else {				usage();				/* NOT REACHED */			}			break;#endif /* DIAGNOSTICS */#ifdef	AUTHENTICATE		case 'e':			if (strcmp(optarg, "debug") == 0) {				extern int auth_debug_mode;				auth_debug_mode = 1;				break;			}			usage();			/* NOTREACHED */			break;#endif	/* AUTHENTICATE */		case 'h':			hostinfo = 0;			break;#ifdef	LINEMODE		case 'l':			alwayslinemode = 1;			break;#endif	/* LINEMODE */		case 'L':			loginprg = strdup(optarg);			/* XXX what if strdup fails? */			break;		case 'n':			keepalive = 0;			break;#ifdef	SecurID		case 's':			/* SecurID required */			require_SecurID = 1;			break;#endif	/* SecurID */		case 'S':#ifdef	HAS_GETTOS			if ((tos = parsetos(optarg, "tcp")) < 0)				fprintf(stderr, "%s%s%s\n",					"telnetd: Bad TOS argument '", optarg,					"'; will try to use default TOS");#else			fprintf(stderr, "%s%s\n", "TOS option unavailable; ",						"-S flag not supported\n");#endif			break;#ifdef	AUTHENTICATE		case 'X':			/*			 * Check for invalid authentication types			 */			auth_disable_name(optarg);			break;#endif	/* AUTHENTICATE */		default:			fprintf(stderr, "telnetd: %c: unknown option\n", ch);			/* FALLTHROUGH */		case '?':			usage();			/* NOTREACHED */		}	}	argc -= optind;	argv += optind;	if (debug) {	    int s, ns;	    socklen_t foo;	    struct servent *sp;	    struct sockaddr_in sn;	    memset(&sn, 0, sizeof(sn));	    sn.sin_family = AF_INET;	    if (argc > 1) {		usage();		/* NOTREACHED */	    } else if (argc == 1) {		    if ((sp = getservbyname(*argv, "tcp"))!=NULL) {			sn.sin_port = sp->s_port;		    } 		    else {			int pt = atoi(*argv);			if (pt <= 0) {			    fprintf(stderr, "telnetd: %s: bad port number\n",				    *argv);			    usage();			    /* NOTREACHED */			}			sn.sin_port = htons(pt);		   }	    } else {		sp = getservbyname("telnet", "tcp");		if (sp == 0) {		    fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");		    exit(1);		}		sn.sin_port = sp->s_port;	    }	    s = socket(AF_INET, SOCK_STREAM, 0);	    if (s < 0) {		    perror("telnetd: socket");;		    exit(1);	    }	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));	    if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {		perror("bind");		exit(1);	    }	    if (listen(s, 1) < 0) {		perror("listen");		exit(1);	    }	    foo = sizeof(sn);	    ns = accept(s, (struct sockaddr *)&sn, &foo);	    if (ns < 0) {		perror("accept");		exit(1);	    }	    (void) dup2(ns, 0);	    (void) close(ns);	    (void) close(s);	} else if (argc > 0) {		usage();		/* NOT REACHED */	}	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);	fromlen = sizeof (from);	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {		fprintf(stderr, "%s: ", progname);		perror("getpeername");		_exit(1);	}	if (keepalive &&	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");	}#if	defined(HAS_IPPROTO_IP) && defined(IP_TOS)	{# if	defined(HAS_GETTOS)		struct tosent *tp;		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))			tos = tp->t_tos;# endif		if (tos < 0)			tos = 020;	/* Low Delay bit */		if (tos		   && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)		   && (errno != ENOPROTOOPT) )			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");	}#endif	/* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */	net = 0;	doit(&from);	/* NOTREACHED */	return 0;}  /* end of main */voidusage(void){	fprintf(stderr, "Usage: telnetd");#ifdef	AUTHENTICATE	fprintf(stderr, " [-a (debug|other|user|valid|off)]\n\t");#endif#ifdef BFTPDAEMON	fprintf(stderr, " [-B]");#endif	fprintf(stderr, " [-debug]");#ifdef DIAGNOSTICS	fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");#endif#ifdef	AUTHENTICATE	fprintf(stderr, " [-edebug]");#endif	fprintf(stderr, " [-h]");#ifdef LINEMODE	fprintf(stderr, " [-l]");#endif	fprintf(stderr, " [-L login_program]");	fprintf(stderr, " [-n]");#ifdef	SecurID	fprintf(stderr, " [-s]");#endif#ifdef	AUTHENTICATE	fprintf(stderr, " [-X auth-type]");#endif	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 void _gettermname(void);staticintgetterminaltype(char *name){    int retval = -1;    (void)name;    settimer(baseline);#if defined(AUTHENTICATE)    /*     * 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);    }#endif#if	defined(ENCRYPT)    send_will(TELOPT_ENCRYPT, 1);#endif    send_do(TELOPT_TTYPE, 1);    send_do(TELOPT_TSPEED, 1);    send_do(TELOPT_XDISPLOC, 1);    send_do(TELOPT_ENVIRON, 1);    while (#if	defined(ENCRYPT)	   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_ENVIRON)) {	ttloop();    }#if	defined(ENCRYPT)    /*     * 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)) {	netoprintf("%c%c%c%c%c%c", 		   IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE);    }    if (his_state_is_will(TELOPT_XDISPLOC)) {	netoprintf("%c%c%c%c%c%c", 		   IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE);    }    if (his_state_is_will(TELOPT_ENVIRON)) {	netoprintf("%c%c%c%c%c%c", 		   IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE);    }    if (his_state_is_will(TELOPT_TTYPE)) {       netoprintf("%c%c%c%c%c%c", 		  IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE);    }    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_ENVIRON)) {	while (sequenceIs(environsubopt, 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)) {	    /*	     * Due to state.c, terminaltype points to a static char[41].	     * Therefore, this assert cannot fail, and therefore, strings	     * arising from "terminaltype" can be safely strcpy'd into	     * first[] or last[].	     */	    assert(strlen(terminaltype) < sizeof(first));	    strcpy(first, terminaltype);	    for(;;) {		/*		 * Save the unknown name, and request the next name.		 */		strcpy(last, terminaltype);		_gettermname();		assert(strlen(terminaltype) < sizeof(first));		if (terminaltypeok(terminaltype))		    break;		if (!strcmp(last, terminaltype) ||		    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 (!strcmp(first, terminaltype))			break;		    /*		     * Get the terminal name one more time, so that		     * RFC1091 compliant telnets will cycle back to		     * the start of the list.		     */		     _gettermname();		    assert(strlen(terminaltype) < sizeof(first));		    if (strcmp(first, terminaltype)) {			/*			 * first[] came from terminaltype, so it must fit			 * back in.			 */			strcpy(terminaltype, first);		    }		    break;		}	    }	}    }    return(retval);}  /* end of getterminaltype */staticvoid_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);    netoprintf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE);    while (sequenceIs(ttypesubopt, baseline))	ttloop();}static intterminaltypeok(const char *s){    /* char buf[2048]; */    if (terminaltype == NULL)	return(1);    /*     * Fix from Chris Evans: if it has a / in it, termcap will     * treat it as a filename. Oops.     */    if (strchr(s, '/')) {	return 0;    }    /*     * If it's absurdly long, accept it without asking termcap.     *     * This means that it won't get seen again until after login,     * at which point exploiting buffer problems in termcap doesn't     * gain one anything.     *     * It's possible this limit ought to be raised to 128, but nothing     * in my termcap is more than 64, 64 is _plenty_ for most, and while     * buffers aren't likely to be smaller than 64, they might be 80 and     * thus less than 128.     */    if (strlen(s) > 63) {       return 0;    }    /*     * tgetent() will return 1 if the type is known, and     * 0 if it is not known.  If it returns -1, it couldn't     * open the database.  But if we can't open the database,     * it won't help to say we failed, because we won't be     * able to verify anything else.  So, we treat -1 like 1.     */

⌨️ 快捷键说明

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