Ejemplo n.º 1
0
int tn_ini( void )
{
    sgaflg = 0;                         /* SGA flag starts out this way. */
    if (send_iac( WILL, TELOPT_TTYPE )) return( -1 );
    if (send_iac( DO, TELOPT_SGA )) return( -1 );

/*
 *  The ECHO negotiations are not necessary for talking to full-duplex
 *  systems, and they don't seem to do any good when sent to half-duplex
 *  ones -- they still refuse to echo, and what's worse, they get into
 *  prolonged negotiation loops.  Real telnet sends only the two above
 *  at the beginning of a connection.
 */

    if (send_iac(WONT,TELOPT_ECHO)) return( -1 );  /* I won't echo. */
    if (send_iac(DO,TELOPT_ECHO)) return( -1 );	   /* Please, you echo. */
    return(0);
}
Ejemplo n.º 2
0
int tn_sttyp(void)
{                            /* Send telnet terminal type. */
    char *ttn;
    int ttl;                 /* Name & length of terminal type. */

    ttn = termtype;		/* we already got this from environment */
    if ((*ttn == 0) || ((ttl = strlen(ttn)) >= TSBUFSIZ)) {
        ttn = "UNKNOWN";
        ttl = 7;
    }
    ttn = strcpy(&sb[1],ttn);		/* Copy to subnegotiation buffer */
    ttn = strchr( strupr(ttn), 0 );

    *sb    = 0;				/* 'is'... */
    *ttn++ = IAC;
    *ttn   = SE;

    if (send_iac(SB,TELOPT_TTYPE))	/* Send: Terminal Type */
	return(-1);

    sock_fastwrite( s, sb, ttl+3 );
    return(0);
}
Ejemplo n.º 3
0
	/* We rely on that there is space in the buffer for now.  */
	char *b = ts->buf2 + ts->rdidx2;
	*b++ = IAC;
	*b++ = command;
	*b++ = option;
	ts->rdidx2 += 3;
	ts->size2 += 3;
}


static struct tsession *
#ifdef CONFIG_FEATURE_TELNETD_INETD
make_new_session(void)
#else /* CONFIG_FEATURE_TELNETD_INETD */
make_new_session(int sockfd)
#endif /* CONFIG_FEATURE_TELNETD_INETD */
{
	struct termios termbuf;
	int pty, pid;
	char tty_name[32];
	struct tsession *ts = malloc(sizeof(struct tsession) + BUFSIZE * 2);

	ts->buf1 = (char *)(&ts[1]);
	ts->buf2 = ts->buf1 + BUFSIZE;

#ifdef CONFIG_FEATURE_TELNETD_INETD
	ts->sockfd_read = 0;
	ts->sockfd_write = 1;
#else /* CONFIG_FEATURE_TELNETD_INETD */
	ts->sockfd = sockfd;
#endif /* CONFIG_FEATURE_TELNETD_INETD */

	ts->rdidx1 = ts->wridx1 = ts->size1 = 0;
	ts->rdidx2 = ts->wridx2 = ts->size2 = 0;

#ifdef CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT
	/* initialize it with the timeout value*/
	ts->timeout_time = time(NULL) + TIMEOUT;
#endif /* CONFIG_FEATURE_TELNETD_INACTIVE_TIMEOUT */	

	/* Got a new connection, set up a tty and spawn a shell.  */

	pty = getpty(tty_name);

	if (pty < 0) {
		syslog(LOG_ERR, "All network ports in use!");
		return 0;
	}

	if (pty > maxfd)
		maxfd = pty;

	ts->ptyfd = pty;

	/* Make the telnet client understand we will echo characters so it
	 * should not do it locally. We don't tell the client to run linemode,
	 * because we want to handle line editing and tab completion and other
	 * stuff that requires char-by-char support.
	 */

	send_iac(ts, DO, TELOPT_ECHO);
	send_iac(ts, DO, TELOPT_NAWS);
	send_iac(ts, DO, TELOPT_LFLOW);
	send_iac(ts, WILL, TELOPT_ECHO);
	send_iac(ts, WILL, TELOPT_SGA);


	if ((pid = fork()) < 0) {
		syslog(LOG_ERR, "Can`t forking");
	}
	if (pid == 0) {
		/* In child, open the child's side of the tty.  */
		int i;

		for(i = 0; i <= maxfd; i++)
			close(i);
		/* make new process group */
		setsid();

		if (open(tty_name, O_RDWR /*| O_NOCTTY*/) < 0) {
			syslog(LOG_ERR, "Could not open tty");
			exit(1);
			}
		dup(0);
		dup(0);

		tcsetpgrp(0, getpid());

		/* The pseudo-terminal allocated to the client is configured to operate in
		 * cooked mode, and with XTABS CRMOD enabled (see tty(4)).
		 */

		tcgetattr(0, &termbuf);
		termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
		termbuf.c_oflag |= ONLCR|XTABS;
		termbuf.c_iflag |= ICRNL;
		termbuf.c_iflag &= ~IXOFF;
		/*termbuf.c_lflag &= ~ICANON;*/
		tcsetattr(0, TCSANOW, &termbuf);

		print_login_issue(issuefile, NULL);

		/* exec shell, with correct argv and env */
		execv(loginpath, (char *const *)argv_init);

		/* NOT REACHED */
		syslog(LOG_ERR, "execv error");
		exit(1);
	}

	ts->shell_pid = pid;

	return ts;
}
Ejemplo n.º 4
0
static int read_pty(int minor)
{ /* Characters written to the client side*/
   unsigned char  value;
   unsigned int  omod;
   int      count;
   int      result;
   pty_t      *pty=telnet_ptys+minor;

   count=read(pty->socket,&value,sizeof(value));
   if (count<0)
    return -1;

   if (count<1) {
      /* Unfortunately, there is no way of passing an EOF
       * condition through the termios driver. Hence, we
       * resort to an ugly hack. Setting cindex>ccount
       * causes the termios driver to return a read count
       * of '0' which is what we want here. We leave
       * 'errno' untouched.
       */
      pty->ttyp->cindex=pty->ttyp->ccount+1;
      return pty->ttyp->termios.c_cc[VEOF];
   };

   omod=pty->iac_mode;
   pty->iac_mode=0;
   switch(omod & 0xff) {
       case IAC_ESC:
           switch(value) {
               case IAC_ESC :
                   /* in case this is an ESC ESC sequence in SB mode */
                   pty->iac_mode = omod>>8;
                   return IAC_ESC;
               case IAC_DONT:
               case IAC_DO  :
               case IAC_WONT:
               case IAC_WILL:
                   pty->iac_mode=value;
                   return -1;
               case IAC_SB  :
#if DEBUG & DEBUG_DETAIL
                   printk("SB\n");
#endif
                   pty->iac_mode=value;
                   pty->sb_ind=0;
                   return -100;
               case IAC_GA  :
                   return -1;
               case IAC_EL  :
                   return 0x03; /* Ctrl-C*/
               case IAC_EC  :
                   return '\b';
               case IAC_AYT :
                   write(pty->socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
                   return -1;
               case IAC_AO  :
                   return -1;
               case IAC_IP  :
                   write(pty->socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
                   return -1;
               case IAC_BRK :
                   write(pty->socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
                   return -1;
               case IAC_DMARK:
                   return -2;
               case IAC_NOP :
                   return -1;
               case IAC_SE  :
#if DEBUG & DEBUG_DETAIL
                  {
                  int i;
                  printk("SE");
                  for (i=0; i<pty->sb_ind; i++)
                    printk(" %02x",pty->sb_buf[i]);
                  printk("\n");
                  }
#endif
                  handleSB(pty);
               return -101;
               case IAC_EOR :
                   return -102;
               default      :
                   return -1;
           };
           break;

       case IAC_SB:
           pty->iac_mode=omod;
           if (IAC_ESC==value) {
             pty->iac_mode=(omod<<8)|value;
           } else {
             if (pty->sb_ind < SB_MAX)
               pty->sb_buf[pty->sb_ind++]=value;
           }
           return -1;

       case IAC_WILL:
           if (value==34){
              send_iac(minor,IAC_DONT,   34);  /*LINEMODE*/
              send_iac(minor,IAC_DO  ,    1);  /*ECHO    */
           } else if (value==31) {
              send_iac(minor,IAC_DO  ,   31);  /*NAWS    */
#if DEBUG & DEBUG_DETAIL
              printk("replied DO NAWS\n");
#endif
           } else {
              send_iac(minor,IAC_DONT,value);
           }
           return -1;
       case IAC_DONT:
           return -1;
       case IAC_DO  :
           if (value==3) {
              send_iac(minor,IAC_WILL,    3);  /* GO AHEAD*/
           } else  if (value==1) {
              /* ECHO */
           } else {
              send_iac(minor,IAC_WONT,value);
           };
           return -1;
       case IAC_WONT:
           if (value==1) {
             send_iac(minor,IAC_WILL,    1);
           } else { /* ECHO */
             send_iac(minor,IAC_WONT,value);
           }
           return -1;
       default:
           if (value==IAC_ESC) {
              pty->iac_mode=value;
              return -1;
           } else {
              result=value;
              if ( 0
#if 0               /* pass CRLF through - they should use termios to handle it */
                 ||  ((value=='\n') && (pty->last_cr))
#endif
                /* but map telnet CRNUL to CR down here */
                 || ((value==0) && pty->last_cr)
                ) result=-1;
               pty->last_cr=(value=='\r');
               return result;
           };
   };
  /* should never get here but keep compiler happy */
  return -1;
}
Ejemplo n.º 5
0
static struct tsession *
make_new_session(int sockfd)
{
	struct termios termbuf;
	int pty, pid;
	static char tty_name[32];
	struct tsession *ts = (struct tsession *)malloc(sizeof(struct tsession));
	int t1, t2;
#ifdef USE_ISSUE
	FILE *fp;
	int chr;
#endif
	ts->buf1 = (char *)malloc(BUFSIZE);
	ts->buf2 = (char *)malloc(BUFSIZE);

	ts->sockfd = sockfd;

	ts->rdidx1 = ts->wridx1 = ts->size1 = 0;
	ts->rdidx2 = ts->wridx2 = ts->size2 = 0;

	/* Got a new connection, set up a tty and spawn a shell.  */

	pty = getpty(tty_name);

	if (pty < 0) {
		fprintf(stderr, "All network ports in use!\n");
		return 0;
	}

	if (pty > maxfd)
		maxfd = pty;

	ts->ptyfd = pty;

	/* Make the telnet client understand we will echo characters so it 
	 * should not do it locally. We don't tell the client to run linemode,
	 * because we want to handle line editing and tab completion and other
	 * stuff that requires char-by-char support.
	 */

	send_iac(ts, DO, TELOPT_ECHO);
	send_iac(ts, DO, TELOPT_LFLOW);
	send_iac(ts, WILL, TELOPT_ECHO);
	send_iac(ts, WILL, TELOPT_SGA);


	if ((pid = fork()) < 0) {
		perror("fork");
	}
	if (pid == 0) {
		/* In child, open the child's side of the tty.  */
		int i, t;

		for(i = 0; i <= maxfd; i++)
			close(i);

		/* make new process group */
		if (setsid() < 0)
			perror_msg_and_die("setsid");
		t = open(tty_name, O_RDWR | O_NOCTTY);
		//t = open(tty_name, O_RDWR);
		if (t < 0)
			perror_msg_and_die("Could not open tty");

		t1 = dup(0);
		t2 = dup(1);

		tcsetpgrp(0, getpid());
		if (ioctl(t, TIOCSCTTY, NULL)) {
			perror_msg_and_die("could not set controlling tty");
		} 
   
		/* The pseudo-terminal allocated to the client is configured to operate in
		 * cooked mode, and with XTABS CRMOD enabled (see tty(4)).
		 */

		tcgetattr(t, &termbuf);
		termbuf.c_lflag |= ECHO; /* if we use readline we dont want this */
		termbuf.c_oflag |= ONLCR|XTABS;
		termbuf.c_iflag |= ICRNL;
		termbuf.c_iflag &= ~IXOFF;
		/* termbuf.c_lflag &= ~ICANON; */
		tcsetattr(t, TCSANOW, &termbuf);

		DEBUG_OUT("stdin, stdout, stderr: %d %d %d\n", t, t1, t2);
#ifdef USE_ISSUE
		/* Display ISSUE_FILE */
		if ((fp = fopen(ISSUE_FILE, "r")) != NULL) {
			DEBUG_OUT(" Open & start display %s\n", ISSUE_FILE);
			while ((chr=fgetc(fp)) != EOF) { 
				if (chr == '\n') fputc('\r', stdout);
				fputc(chr, stdout);
			}
			fclose(fp);
		}
#endif
		/* exec shell, with correct argv and env */
		execv(loginpath, argv_init);

	        /* NOT REACHED */
		perror_msg_and_die("execv");
	}

	ts->shell_pid = pid;

	return ts;
}
Ejemplo n.º 6
0
int tn_doop(int c)
{
    int x, y, n, flag;


    x = ttinc(0) & 0xff;                /* Read command character */

    switch (x) {
      case TELOPT_ECHO:                 /* ECHO negotiation. */
        if (c == WILL) {                /* Host says it will echo. */
	    if (echo) {                 /* Only reply if change required */
		echo = 0;
		if (send_iac(DO,x))  	/* Please do. */
		    return(-1);
	    }
	    return(0);
	}

        if (c == WONT) {                /* Host says it won't echo. */
            if (!echo) {                /* If I'm not echoing already */
		if (send_iac(DONT,x)) /* agree to echo. */
		    return(-1);
		echo = 1;
	    }
	    return(0);
	}

        if (c == DO) {                  /* Host wants me to echo */
	    if (send_iac(WONT,x))	/* I say I won't, */
		return(-1);
	    if (send_iac(DO,x))		/* and ask the host to echo. */
		return(-1);
	    echo = 0;
	    return( 0 );
        }
        if (c == DONT) {                /* Host wants me not to echo */
	    if (send_iac(WONT,x))	/* I say I won't. */
		return(-1);
	    echo = 0;
	    return( 0 );
        }
        return(0);


      case TELOPT_SGA:                  /* Suppress Go-Ahead */
        if (c == WONT) {                /* Host says it won't. */
            sgaflg = 1;                 /* Remember. */
            if (!echo) {                /* If we're not echoing, */
		if (send_iac(DONT,x)) /* acknowledge, */
		    return(-1);
		echo = 1;		/* and switch to local echo. */
	    }
        }
        if (c == WILL) {                /* Host says it will. */
            sgaflg = 0;                 /* Remember. */
            if (echo) {                 /* If I'm echoing now, */
		if (send_iac(DO,x))	/* this is a change, so ACK. */
		    return(-1);
		if (send_iac(DO,TELOPT_ECHO)) /* Request remote echo */
		    return(-1);
            }
        }
        return(0);


      case TELOPT_TTYPE:                /* Terminal Type */
        switch (c) {
          case DO:                      /* DO terminal type. */
	    if (send_iac(WILL,x))    /* Say I'll send it if asked. */
		return(-1);
	    return(0);

	  /* enter subnegociations */
          case SB:
            n = flag = 0;               /* Flag for when done reading SB */
            while (n < TSBUFSIZ) {      /* Loop looking for IAC SE */
                if ((y = ttinc(0)) < 0)
		  return(-1);
		y &= 0xff;              /* Make sure it's just 8 bits. */
		sb[n++] = y;            /* Save what we got in buffer. */

                if (y == IAC) {         /* If this is an IAC */
                    flag = 1;           /* set the flag. */
                } else {                /* Otherwise, */
                    if (flag && y == SE) /* if this is SE which immediately */
                      break;            /* follows IAC, we're done. */
                    else flag = 0;      /* Otherwise turn off flag. */
                }
	    }
	    if (!flag)
	       return(-1);      /* Make sure we got a valid SB */


	    if ( *sb == 1 ) {
		if ( tn_sttyp() )
                  return(-1);
	    };


          default:                      /* Others, ignore */
            return(0);
        }

      default:                          /* All others: refuse */
        switch(c) {
          case WILL:                    /* You will? */
	    if (send_iac(DONT,x))	/* Please don't. */
		return(-1);
            break;
          case DO:                      /* You want me to? */
	    if (send_iac(WONT,x))	/* I won't. */
		return(-1);
	    if (send_iac(DONT,x))	/* Don't you either. */
		return(-1);
            break;
          case DONT:                    /* (fall thru...) */
	    if (send_iac(WONT,x))	/* I won't. */
		return(-1);
          case WONT:                    /* You won't? */
            break;                      /* Good. */
          }
        return(0);
    }
}