Esempio n. 1
0
static void trans_data_sock2pty()
{
    char buf[512];
    int ret;
    
    ret=read_reliable(fd_conn, buf, sizeof(buf));
//    DBG_PRINT("ret=%d", ret);
    if (ret<=0)
    {
        term_session();
        return;
    }

    remove_iacs((void *)buf, ret, &ret);
    if (ret>0)
        write_certain_bytes(fd_pty_master, buf, ret);
    //for (i=0;i<ret;i++)
    //    DBG_PRINT("%02hhx-%c", buf[i], buf[i]);
}
Esempio n. 2
0
int
telnetd_main(int argc, char **argv)
{
#if !defined(CONFIG_FEATURE_TELNETD_INETD)  || defined(IFX_INETD_ENHANCEMENT)
	int master_fd;
#endif
#ifndef CONFIG_FEATURE_TELNETD_INETD
	struct sockaddr_in sa;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
	fd_set rdfdset, wrfdset;
	int selret;
#ifndef CONFIG_FEATURE_TELNETD_INETD
	int on = 1;
	int portnbr = 23;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
	int c;
	static const char options[] =
#ifdef CONFIG_FEATURE_TELNETD_INETD
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
		"f:l:t:";
#else /*CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT*/		
		"f:l:";
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */	
#else /* CONFIG_EATURE_TELNETD_INETD */
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
		"f:l:p:t:";
#else /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */		
		"f:l:p:";
#endif /*CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT*/		
#endif /* CONFIG_FEATURE_TELNETD_INETD */
	int maxlen, w, r;

#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
	struct timeval time_val;
	int daemon_timeout_val = time(NULL) + 120;
#endif
#ifndef CONFIG_LOGIN
	loginpath = DEFAULT_SHELL;
#endif


	for (;;) {
		c = getopt( argc, argv, options);
		if (c == EOF) break;
		switch (c) {
			case 'f':
				issuefile = optarg;
				break;
			case 'l':
				loginpath = optarg;
				break;
#ifndef CONFIG_FEATURE_TELNETD_INETD
			case 'p':
				portnbr = atoi(optarg);
				break;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
			case 't':
				TIMEOUT = atoi(optarg);
				break;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT*/				
			default:
				bb_show_usage();
		}
	}

	if (access(loginpath, X_OK) < 0) {
		bb_error_msg_and_die ("'%s' unavailable.", loginpath);
	}

	argv_init[0] = loginpath;

	openlog(bb_applet_name, 0, LOG_USER);
	
#ifndef IFX_INETD_ENHANCEMENT 
#ifdef CONFIG_FEATURE_TELNETD_INETD
	maxfd = 1;
	sessions = make_new_session();
#else /* CONFIG_EATURE_TELNETD_INETD */
	sessions = 0;

	/* Grab a TCP socket.  */
	master_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (master_fd < 0) {
		bb_perror_msg_and_die("socket");
	}
	(void)setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

	/* Set it to listen to specified port.  */

	memset((void *)&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_port = htons(portnbr);

	if (bind(master_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
		bb_perror_msg_and_die("bind");
	}

	if (listen(master_fd, 1) < 0) {
		bb_perror_msg_and_die("listen");
	}

	if (daemon(0, 0) < 0)
		bb_perror_msg_and_die("daemon");
	maxfd = master_fd;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
#else /* IFX_INETD_ENHANCEMENT */
	sessions = 0;
	master_fd = 0;
	maxfd = master_fd;
#endif /* IFX_INETD_ENHANCEMENT */


	do {
		struct tsession *ts;

		FD_ZERO(&rdfdset);
		FD_ZERO(&wrfdset);

		/* select on the master socket, all telnet sockets and their
		 * ptys if there is room in their respective session buffers.
		 */

#ifndef CONFIG_FEATURE_TELNETD_INETD
		FD_SET(master_fd, &rdfdset);
#endif /* CONFIG_FEATURE_TELNETD_INETD */

		ts = sessions;
#ifndef CONFIG_FEATURE_TELNETD_INETD
		while (ts) {
#endif /* CONFIG_FEATURE_TELNETD_INETD */
			/* buf1 is used from socket to pty
			 * buf2 is used from pty to socket
			 */
			if (ts->size1 > 0) {
				FD_SET(ts->ptyfd, &wrfdset);  /* can write to pty */
			}
			if (ts->size1 < BUFSIZE) {
#ifdef CONFIG_FEATURE_TELNETD_INETD
				FD_SET(ts->sockfd_read, &rdfdset); /* can read from socket */
#else /* CONFIG_FEATURE_TELNETD_INETD */
				FD_SET(ts->sockfd, &rdfdset); /* can read from socket */
#endif /* CONFIG_FEATURE_TELNETD_INETD */
			}
			if (ts->size2 > 0) {
#ifdef CONFIG_FEATURE_TELNETD_INETD
				FD_SET(ts->sockfd_write, &wrfdset); /* can write to socket */
#else /* CONFIG_FEATURE_TELNETD_INETD */
				FD_SET(ts->sockfd, &wrfdset); /* can write to socket */
#endif /* CONFIG_FEATURE_TELNETD_INETD */
			}
			if (ts->size2 < BUFSIZE) {
				FD_SET(ts->ptyfd, &rdfdset);  /* can read from pty */
			}
#ifndef CONFIG_FEATURE_TELNETD_INETD
			ts = ts->next;
		}
#endif /* CONFIG_FEATURE_TELNETD_INETD */

#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
		time_val.tv_sec = 10;
		time_val.tv_usec = 0;
		selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, &time_val);
#else
		selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0);
#endif

		if (selret < 0)
			break;
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
			// check if the currtime exceeded timeout time
#ifndef CONFIG_FEATURE_TELNETD_INETD
			ts= sessions;
			while(ts)
			{
				struct tsession *next = ts->next; /* in case we free ts. */
#endif /* CONFIG_FEATURE_TELNETD_INETD */					
				if(ts->timeout_time < time(NULL))
				{
					printf("Timed out \n");
					syslog(LOG_ERR,"Session timed out\n");
#ifdef CONFIG_FEATURE_TELNETD_INETD
					exit(0);
#else /* CONFIG_FEATURE_TELNETD_INETD */
					daemon_timeout_val = time(NULL) + 120;
					free_session(ts);
#endif/* CONFIG_FEATURE_TELNETD_INETD */						
				}
#ifndef CONFIG_FEATURE_TELNETD_INETD					
				ts= next;
			}
#endif /* CONFIG_FEATURE_TELNETD_INETD */
			if(selret == 0) {
				if(sessions == NULL && daemon_timeout_val < time(NULL)) {
					printf("Telnetd Timed out \n");
					syslog(LOG_ERR,"Telnetd timed out\n");
					exit(0);
				} else
					continue;
			}
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */

#ifndef CONFIG_FEATURE_TELNETD_INETD
		daemon_timeout_val = time(NULL) + 120;
		/* First check for and accept new sessions.  */
		if (FD_ISSET(master_fd, &rdfdset)) {
			int fd, salen;

			salen = sizeof(sa);
			if ((fd = accept(master_fd, (struct sockaddr *)&sa,
						&salen)) < 0) {
				continue;
			} else {
				/* Create a new session and link it into
					our active list.  */
				struct tsession *new_ts = make_new_session(fd);
				if (new_ts) {
					new_ts->next = sessions;
					sessions = new_ts;
					if (fd > maxfd)
						maxfd = fd;
				} else {
					close(fd);
				}
			}
		}

		/* Then check for data tunneling.  */
		ts = sessions;
		while (ts) { /* For all sessions...  */
#endif /* CONFIG_FEATURE_TELNETD_INETD */
#ifndef CONFIG_FEATURE_TELNETD_INETD
			struct tsession *next = ts->next; /* in case we free ts. */
#endif /* CONFIG_FEATURE_TELNETD_INETD */

			if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset)) {
				int num_totty;
				char *ptr;
				/* Write to pty from buffer 1.  */

				ptr = remove_iacs(ts, &num_totty);

				w = write(ts->ptyfd, ptr, num_totty);
				if (w < 0) {
#ifdef CONFIG_FEATURE_TELNETD_INETD
					exit(0);
#else /* CONFIG_FEATURE_TELNETD_INETD */
					free_session(ts);
					ts = next;
					continue;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
				}
				ts->wridx1 += w;
				ts->size1 -= w;
				if (ts->wridx1 == BUFSIZE)
					ts->wridx1 = 0;
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT				
				//some activity in this session reset the timer
				ts->timeout_time = time(NULL)+ TIMEOUT;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */				
			}

#ifdef CONFIG_FEATURE_TELNETD_INETD
			if (ts->size2 && FD_ISSET(ts->sockfd_write, &wrfdset)) 
#else /* CONFIG_FEATURE_TELNETD_INETD */
			if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset)) 
#endif /* CONFIG_FEATURE_TELNETD_INETD */
			{
				/* Write to socket from buffer 2.  */
				maxlen = MIN(BUFSIZE - ts->wridx2, ts->size2);
#ifdef CONFIG_FEATURE_TELNETD_INETD
				w = write(ts->sockfd_write, ts->buf2 + ts->wridx2, maxlen);
				if (w < 0)
					exit(0);
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT				
				else
					ts->timeout_time = time(NULL)+TIMEOUT;
#endif /*CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT*/				
#else /* CONFIG_FEATURE_TELNETD_INETD */
				w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen);
				if (w < 0) {
					free_session(ts);
					ts = next;
					continue;
				}
#endif /* CONFIG_FEATURE_TELNETD_INETD */
				ts->wridx2 += w;
				ts->size2 -= w;
				if (ts->wridx2 == BUFSIZE)
					ts->wridx2 = 0;
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT				
				//some activity in this session reset the timer
				ts->timeout_time = time(NULL)+ TIMEOUT;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */				
			}

#ifdef CONFIG_FEATURE_TELNETD_INETD
			if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd_read, &rdfdset)) 
#else /* CONFIG_FEATURE_TELNETD_INETD */
			if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset)) 
#endif /* CONFIG_FEATURE_TELNETD_INETD */
			{
				/* Read from socket to buffer 1. */
				maxlen = MIN(BUFSIZE - ts->rdidx1,
						BUFSIZE - ts->size1);
#ifdef CONFIG_FEATURE_TELNETD_INETD
				r = read(ts->sockfd_read, ts->buf1 + ts->rdidx1, maxlen);
				if (!r || (r < 0 && errno != EINTR))
					exit(0);
#else /* CONFIG_FEATURE_TELNETD_INETD */
				r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen);
				if (!r || (r < 0 && errno != EINTR)) {
					free_session(ts);
					ts = next;
					continue;
				}
#endif /* CONFIG_FEATURE_TELNETD_INETD */
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT				
				//some activity in this session reset the timer
				ts->timeout_time = time(NULL)+ TIMEOUT;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */				
				if(!*(ts->buf1 + ts->rdidx1 + r - 1)) {
					r--;
					if(!r)
						continue;
				}
				ts->rdidx1 += r;
				ts->size1 += r;
				if (ts->rdidx1 == BUFSIZE)
					ts->rdidx1 = 0;
			}

			if (ts->size2 < BUFSIZE && FD_ISSET(ts->ptyfd, &rdfdset)) {
				/* Read from pty to buffer 2.  */
				maxlen = MIN(BUFSIZE - ts->rdidx2,
						BUFSIZE - ts->size2);
				r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen);
				if (!r || (r < 0 && errno != EINTR)) {
#ifdef CONFIG_FEATURE_TELNETD_INETD
					exit(0);
#else /* CONFIG_FEATURE_TELNETD_INETD */
					free_session(ts);
					ts = next;
					continue;
#endif /* CONFIG_FEATURE_TELNETD_INETD */
				}
				ts->rdidx2 += r;
				ts->size2 += r;
				if (ts->rdidx2 == BUFSIZE)
					ts->rdidx2 = 0;
#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT				
				//some activity in this session reset the timer
				ts->timeout_time = time(NULL)+ TIMEOUT;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */				
			}

			if (ts->size1 == 0) {
				ts->rdidx1 = 0;
				ts->wridx1 = 0;
			}
			if (ts->size2 == 0) {
				ts->rdidx2 = 0;
				ts->wridx2 = 0;
			}
#ifndef CONFIG_FEATURE_TELNETD_INETD
			ts = next;
		}
#endif /* CONFIG_FEATURE_TELNETD_INETD */

	} while (1);

	return 0;
}
Esempio n. 3
0
int main(int argc, char **argv)
{
	struct sockaddr_in sa;
	int master_fd;
	fd_set rdfdset, wrfdset;
	int selret;
	int on = 1;
	int portnbr = 23;
	int c, ii;
	int daemonize = 0;
	char *interface_name = NULL;
	struct ifreq interface;

#ifdef USE_SYSLOG
	char *appname;
	appname = strrchr (argv [0], '/');
	if (!appname) appname = argv [0];
	    else appname++;
#endif

	/* check if user supplied a port number */

	for (;;) {
		c = getopt( argc, argv, "i:p:l:hd");
		if (c == EOF) break;
		switch (c) {
			case 'p':
				portnbr = atoi(optarg);
				break;
			case 'i':
				interface_name = strdup(optarg);
				break;
			case 'l':
				loginpath = strdup(optarg);
				break;
			case 'd':
				daemonize = 1;
				break;
			case 'h': 
			default:
				show_usage();
				exit(1);
		}
	}

	if (!loginpath) {
		loginpath = SHELLPATH;
		if (access(loginpath, X_OK) < 0) loginpath = "/bin/sh";
	}
	  
	if (access(loginpath, X_OK) < 0) {
		/* workaround: error_msg_and_die has doesn't understand
 		   variable argument lists yet */
		fprintf(stderr,"\"%s\"",loginpath);
		perror_msg_and_die(" is no valid executable!\n");
	}

	printf("telnetd: starting\n");
	printf("  port: %i; interface: %s; login program: %s\n",
		portnbr, (interface_name)?interface_name:"any", loginpath);

	argv_init[0] = loginpath;
	sessions = 0;

	/* Grab a TCP socket.  */

	master_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (master_fd < 0) {
		perror("socket");
		return 1;
	}
	(void)setsockopt(master_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

	/* Set it to listen to specified port */

	memset((void *)&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_port = htons(portnbr);

	/* Set it to listen on the specified interface */

	if (interface_name) {

		strcpy(interface.ifr_name, interface_name);

		/* use ioctl() here as BSD does not have setsockopt() */
		if (ioctl(master_fd, SIOCGIFADDR, &interface) < 0) {
			printf("Please check the NIC you specified with -i option\n");
			perror("ioctl SIOCGFADDR");
			return 1;
		}

		sa.sin_addr = ((struct sockaddr_in *)(&interface.ifr_addr))->sin_addr;
	} else 
		sa.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(master_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
		perror("bind");
		return 1;
	}

	if (listen(master_fd, 1) < 0) {
		perror("listen");
		return 1;
	}

	if (daemonize) 
	{
		DEBUG_OUT("  daemonizing\n");
		if (daemon(0, 1) < 0) perror_msg_and_die("daemon");
	}

#ifdef USE_SYSLOG
	openlog(appname , LOG_NDELAY | LOG_PID, LOG_DAEMON);	
	syslog(LOG_INFO, "%s (port: %i, ifname: %s, login: %s) startup succeeded\n"\
	    , appname, portnbr, (interface_name)?interface_name:"any", loginpath);
	closelog();
#endif

	maxfd = master_fd;

	do {
		struct tsession *ts;

		FD_ZERO(&rdfdset);
		FD_ZERO(&wrfdset);

		/* select on the master socket, all telnet sockets and their
		 * ptys if there is room in their respective session buffers.
		 */

		FD_SET(master_fd, &rdfdset);

		ts = sessions;
		while (ts) {
			/* buf1 is used from socket to pty
			 * buf2 is used from pty to socket
			 */
			if (ts->size1 > 0) {
				FD_SET(ts->ptyfd, &wrfdset);  /* can write to pty */
			}
			if (ts->size1 < BUFSIZE) {
				FD_SET(ts->sockfd, &rdfdset); /* can read from socket */
			}
			if (ts->size2 > 0) {
				FD_SET(ts->sockfd, &wrfdset); /* can write to socket */
			}
			if (ts->size2 < BUFSIZE) {
				FD_SET(ts->ptyfd, &rdfdset);  /* can read from pty */
			}
			ts = ts->next;
		}

		selret = select(maxfd + 1, &rdfdset, &wrfdset, 0, 0);

		if (!selret)
			break;

		/* First check for and accept new sessions.  */
		if (FD_ISSET(master_fd, &rdfdset)) {
			int fd, salen;

			salen = sizeof(sa);	
			if ((fd = accept(master_fd, (struct sockaddr *)&sa,
					 &salen)) < 0) {
				continue;
			} else {
				/* Create a new session and link it into our active list. */
				struct tsession *new_ts;
#ifdef USE_SYSLOG
				openlog(appname , LOG_NDELAY, LOG_DAEMON);	
				syslog(LOG_INFO, "connection from: %s\n", inet_ntoa(sa.sin_addr));
				closelog();
#endif
				new_ts = make_new_session(fd);
				if (new_ts) {
					new_ts->next = sessions;
					sessions = new_ts;
					if (fd > maxfd)
						maxfd = fd;
				} else {
					close(fd);
				}
			}
		}

		/* Then check for data tunneling.  */

		ts = sessions;
		while (ts) { /* For all sessions...  */
			int maxlen, w, r;
			struct tsession *next = ts->next; /* in case we free ts. */

			if (ts->size1 && FD_ISSET(ts->ptyfd, &wrfdset)) {
			    int processed, num_totty;
			    char *ptr;
				/* Write to pty from buffer 1.  */
				
				maxlen = MIN(BUFSIZE - ts->wridx1,
					     ts->size1);
				ptr = remove_iacs(ts->buf1 + ts->wridx1, maxlen, 
					&processed, &num_totty);
		
				/* the difference between processed and num_totty
				   is all the iacs we removed from the stream.
				   Adjust buf1 accordingly. */
				ts->wridx1 += processed - num_totty;
				ts->size1 -= processed - num_totty;

				w = write(ts->ptyfd, ptr, num_totty);
				if (w < 0) {
					perror("write");
					free_session(ts);
					ts = next;
					continue;
				}
				ts->wridx1 += w;
				ts->size1 -= w;
				if (ts->wridx1 == BUFSIZE)
					ts->wridx1 = 0;
			}

			if (ts->size2 && FD_ISSET(ts->sockfd, &wrfdset)) {
				/* Write to socket from buffer 2.  */
				maxlen = MIN(BUFSIZE - ts->wridx2,
					     ts->size2);
				w = write(ts->sockfd, ts->buf2 + ts->wridx2, maxlen);
				if (w < 0) {
					perror("write");
					free_session(ts);
					ts = next;
					continue;
				}
				ts->wridx2 += w;
				ts->size2 -= w;
				if (ts->wridx2 == BUFSIZE)
					ts->wridx2 = 0;
			}

			if (ts->size1 < BUFSIZE && FD_ISSET(ts->sockfd, &rdfdset)) {
				/* Read from socket to buffer 1. */
				maxlen = MIN(BUFSIZE - ts->rdidx1,
					     BUFSIZE - ts->size1);
				r = read(ts->sockfd, ts->buf1 + ts->rdidx1, maxlen);
				if (!r || (r < 0 && errno != EINTR)) {
					free_session(ts);
					ts = next;
					continue;
				}
				if(!*(ts->buf1 + ts->rdidx1 + r - 1)) {
					r--;
					if(!r)
						continue;
				}
				ts->rdidx1 += r;
				ts->size1 += r;
				if (ts->rdidx1 == BUFSIZE)
					ts->rdidx1 = 0;
			}

			if (ts->size2 < BUFSIZE && FD_ISSET(ts->ptyfd, &rdfdset)) {
				/* Read from pty to buffer 2.  */
				maxlen = MIN(BUFSIZE - ts->rdidx2,
					     BUFSIZE - ts->size2);
				r = read(ts->ptyfd, ts->buf2 + ts->rdidx2, maxlen);
				if (!r || (r < 0 && errno != EINTR)) {
					free_session(ts);
					ts = next;
					continue;
				}
				for (ii=0; ii < r; ii++)
				  if (*(ts->buf2 + ts->rdidx2 + ii) == 3)
				    fprintf(stderr, "found <CTRL>-<C> in data!\n");
				ts->rdidx2 += r;
				ts->size2 += r;
				if (ts->rdidx2 == BUFSIZE)
					ts->rdidx2 = 0;
			}

			if (ts->size1 == 0) {
				ts->rdidx1 = 0;
				ts->wridx1 = 0;
			}
			if (ts->size2 == 0) {
				ts->rdidx2 = 0;
				ts->wridx2 = 0;
			}
			ts = next;
		}

	} while (1);

	return 0;
}