Exemple #1
0
void
send_dont(int c, int init)
{
    if (init) {
	if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
				my_want_state_is_dont(c))
	    return;
	set_my_want_state_dont(c);
	do_dont_resp[c]++;
    }
    if (telnetport < 0)
	return;
    NET2ADD(IAC, DONT);
    NETADD(c);
    printoption("SENT", DONT, c);
}
Exemple #2
0
static void send_negotiation(struct connectdata *conn, int cmd, int option)
{
   unsigned char buf[3];
   ssize_t bytes_written;
   int err;
   struct SessionHandle *data = conn->data;

   buf[0] = CURL_IAC;
   buf[1] = (unsigned char)cmd;
   buf[2] = (unsigned char)option;

   bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
   if(bytes_written < 0) {
     err = SOCKERRNO;
     failf(data,"Sending data failed (%d)",err);
   }

   printoption(conn->data, "SENT", cmd, option);
}
/*
 * The will/wont/do/dont state machines are based on Dave Borman's
 * Telnet option processing state machine.
 *
 * These correspond to the following states:
 *	my_state = the last negotiated state
 *	want_state = what I want the state to go to
 *	want_resp = how many requests I have sent
 * All state defaults are negative, and resp defaults to 0.
 *
 * When initiating a request to change state to new_state:
 *
 * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) {
 *	do nothing;
 * } else {
 *	want_state = new_state;
 *	send new_state;
 *	want_resp++;
 * }
 *
 * When receiving new_state:
 *
 * if (want_resp) {
 *	want_resp--;
 *	if (want_resp && (new_state == my_state))
 *		want_resp--;
 * }
 * if ((want_resp == 0) && (new_state != want_state)) {
 *	if (ok_to_switch_to new_state)
 *		want_state = new_state;
 *	else
 *		want_resp++;
 *	send want_state;
 * }
 * my_state = new_state;
 *
 * Note that new_state is implied in these functions by the function itself.
 * will and do imply positive new_state, wont and dont imply negative.
 *
 * Finally, there is one catch.  If we send a negative response to a
 * positive request, my_state will be the positive while want_state will
 * remain negative.  my_state will revert to negative when the negative
 * acknowlegment arrives from the peer.  Thus, my_state generally tells
 * us not only the last negotiated state, but also tells us what the peer
 * wants to be doing as well.  It is important to understand this difference
 * as we may wish to be processing data streams based on our desired state
 * (want_state) or based on what the peer thinks the state is (my_state).
 *
 * This all works fine because if the peer sends a positive request, the data
 * that we receive prior to negative acknowlegment will probably be affected
 * by the positive state, and we can process it as such (if we can; if we
 * can't then it really doesn't matter).  If it is that important, then the
 * peer probably should be buffering until this option state negotiation
 * is complete.
 *
 */
void send_do(int option, int init) {
    if (init) {
        if ((do_dont_resp[option] == 0 && his_state_is_will(option)) ||
                his_want_state_is_will(option))
            return;
        /*
         * Special case for TELOPT_TM:  We send a DO, but pretend
         * that we sent a DONT, so that we can send more DOs if
         * we want to.
         */
        if (option == TELOPT_TM)
            set_his_want_state_wont(option);
        else
            set_his_want_state_will(option);
        do_dont_resp[option]++;
    }
    netoprintf((char *)doopt, option);

    DIAG(TD_OPTIONS, printoption("td: send do", option));
}
Exemple #4
0
int
telrcv(void)
{
    int c;
    int scc;
    unsigned char *sbp;
    int count;
    int returnValue = 0;

    scc = 0;
    count = 0;
    while (TTYROOM() > 2) {
	if (scc == 0) {
	    if (count) {
		ring_consumed(&netiring, count);
		returnValue = 1;
		count = 0;
	    }
	    sbp = netiring.consume;
	    scc = ring_full_consecutive(&netiring);
	    if (scc == 0) {
		/* No more data coming in */
		break;
	    }
	}

	c = *sbp++ & 0xff, scc--; count++;
#ifdef	ENCRYPTION
	if (decrypt_input)
		c = (*decrypt_input)(c);
#endif	/* ENCRYPTION */

	switch (telrcv_state) {

	case TS_CR:
	    telrcv_state = TS_DATA;
	    if (c == '\0') {
		break;	/* Ignore \0 after CR */
	    }
	    else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
		TTYADD(c);
		break;
	    }
	    /* Else, fall through */

	case TS_DATA:
	    if (c == IAC) {
		telrcv_state = TS_IAC;
		break;
	    }
		    /*
		     * The 'crmod' hack (see following) is needed
		     * since we can't * set CRMOD on output only.
		     * Machines like MULTICS like to send \r without
		     * \n; since we must turn off CRMOD to get proper
		     * input, the mapping is done here (sigh).
		     */
	    if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
		if (scc > 0) {
		    c = *sbp&0xff;
#ifdef	ENCRYPTION
		    if (decrypt_input)
			c = (*decrypt_input)(c);
#endif	/* ENCRYPTION */
		    if (c == 0) {
			sbp++, scc--; count++;
			/* a "true" CR */
			TTYADD('\r');
		    } else if (my_want_state_is_dont(TELOPT_ECHO) &&
					(c == '\n')) {
			sbp++, scc--; count++;
			TTYADD('\n');
		    } else {
#ifdef	ENCRYPTION
			if (decrypt_input)
			    (*decrypt_input)(-1);
#endif	/* ENCRYPTION */

			TTYADD('\r');
			if (crmod) {
				TTYADD('\n');
			}
		    }
		} else {
		    telrcv_state = TS_CR;
		    TTYADD('\r');
		    if (crmod) {
			    TTYADD('\n');
		    }
		}
	    } else {
		TTYADD(c);
	    }
	    continue;

	case TS_IAC:
process_iac:
	    switch (c) {

	    case WILL:
		telrcv_state = TS_WILL;
		continue;

	    case WONT:
		telrcv_state = TS_WONT;
		continue;

	    case DO:
		telrcv_state = TS_DO;
		continue;

	    case DONT:
		telrcv_state = TS_DONT;
		continue;

	    case DM:
		    /*
		     * We may have missed an urgent notification,
		     * so make sure we flush whatever is in the
		     * buffer currently.
		     */
		printoption("RCVD", IAC, DM);
		SYNCHing = 1;
		(void) ttyflush(1);
		SYNCHing = stilloob();
		settimer(gotDM);
		break;

	    case SB:
		SB_CLEAR();
		telrcv_state = TS_SB;
		continue;

	    case IAC:
		TTYADD(IAC);
		break;

	    case NOP:
	    case GA:
	    default:
		printoption("RCVD", IAC, c);
		break;
	    }
	    telrcv_state = TS_DATA;
	    continue;

	case TS_WILL:
	    printoption("RCVD", WILL, c);
	    willoption(c);
	    telrcv_state = TS_DATA;
	    continue;

	case TS_WONT:
	    printoption("RCVD", WONT, c);
	    wontoption(c);
	    telrcv_state = TS_DATA;
	    continue;

	case TS_DO:
	    printoption("RCVD", DO, c);
	    dooption(c);
	    if (c == TELOPT_NAWS) {
		sendnaws();
	    } else if (c == TELOPT_LFLOW) {
		localflow = 1;
		setcommandmode();
		setconnmode(0);
	    }
	    telrcv_state = TS_DATA;
	    continue;

	case TS_DONT:
	    printoption("RCVD", DONT, c);
	    dontoption(c);
	    flushline = 1;
	    setconnmode(0);	/* set new tty mode (maybe) */
	    telrcv_state = TS_DATA;
	    continue;

	case TS_SB:
	    if (c == IAC) {
		telrcv_state = TS_SE;
	    } else {
		SB_ACCUM(c);
	    }
	    continue;

	case TS_SE:
	    if (c != SE) {
		if (c != IAC) {
		    /*
		     * This is an error.  We only expect to get
		     * "IAC IAC" or "IAC SE".  Several things may
		     * have happend.  An IAC was not doubled, the
		     * IAC SE was left off, or another option got
		     * inserted into the suboption are all possibilities.
		     * If we assume that the IAC was not doubled,
		     * and really the IAC SE was left off, we could
		     * get into an infinate loop here.  So, instead,
		     * we terminate the suboption, and process the
		     * partial suboption if we can.
		     */
		    SB_ACCUM(IAC);
		    SB_ACCUM(c);
		    subpointer -= 2;
		    SB_TERM();

		    printoption("In SUBOPTION processing, RCVD", IAC, c);
		    suboption();	/* handle sub-option */
		    telrcv_state = TS_IAC;
		    goto process_iac;
		}
		SB_ACCUM(c);
		telrcv_state = TS_SB;
	    } else {
		SB_ACCUM(IAC);
		SB_ACCUM(SE);
		subpointer -= 2;
		SB_TERM();
		suboption();	/* handle sub-option */
		telrcv_state = TS_DATA;
	    }
	}
    }
    if (count)
	ring_consumed(&netiring, count);
    return returnValue||count;
}
Exemple #5
0
static
void telrcv(struct connectdata *conn,
            unsigned char *inbuf,       /* Data received from socket */
            ssize_t count)              /* Number of bytes received */
{
  unsigned char c;
  int in = 0;
  struct SessionHandle *data = conn->data;
  struct TELNET *tn = (struct TELNET *)data->reqdata.proto.telnet;

  while(count--)
  {
    c = inbuf[in++];

    switch (tn->telrcv_state)
    {
      case CURL_TS_CR:
        tn->telrcv_state = CURL_TS_DATA;
        if (c == '\0')
        {
          break;   /* Ignore \0 after CR */
        }

        Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
        continue;

      case CURL_TS_DATA:
        if (c == CURL_IAC)
        {
          tn->telrcv_state = CURL_TS_IAC;
          break;
        }
        else if(c == '\r')
        {
          tn->telrcv_state = CURL_TS_CR;
        }

        Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
        continue;

      case CURL_TS_IAC:
      process_iac:
      switch (c)
      {
        case CURL_WILL:
          tn->telrcv_state = CURL_TS_WILL;
          continue;
        case CURL_WONT:
          tn->telrcv_state = CURL_TS_WONT;
          continue;
        case CURL_DO:
          tn->telrcv_state = CURL_TS_DO;
          continue;
        case CURL_DONT:
          tn->telrcv_state = CURL_TS_DONT;
          continue;
        case CURL_SB:
          CURL_SB_CLEAR(tn);
          tn->telrcv_state = CURL_TS_SB;
          continue;
        case CURL_IAC:
          Curl_client_write(conn, CLIENTWRITE_BODY, (char *)&c, 1);
          break;
        case CURL_DM:
        case CURL_NOP:
        case CURL_GA:
        default:
          printoption(data, "RCVD", CURL_IAC, c);
          break;
      }
      tn->telrcv_state = CURL_TS_DATA;
      continue;

      case CURL_TS_WILL:
        printoption(data, "RCVD", CURL_WILL, c);
        tn->please_negotiate = 1;
        rec_will(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        continue;

      case CURL_TS_WONT:
        printoption(data, "RCVD", CURL_WONT, c);
        tn->please_negotiate = 1;
        rec_wont(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        continue;

      case CURL_TS_DO:
        printoption(data, "RCVD", CURL_DO, c);
        tn->please_negotiate = 1;
        rec_do(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        continue;

      case CURL_TS_DONT:
        printoption(data, "RCVD", CURL_DONT, c);
        tn->please_negotiate = 1;
        rec_dont(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        continue;

      case CURL_TS_SB:
        if (c == CURL_IAC)
        {
          tn->telrcv_state = CURL_TS_SE;
        }
        else
        {
          CURL_SB_ACCUM(tn,c);
        }
        continue;

      case CURL_TS_SE:
        if (c != CURL_SE)
        {
          if (c != CURL_IAC)
          {
            /*
             * This is an error.  We only expect to get "IAC IAC" or "IAC SE".
             * Several things may have happend.  An IAC was not doubled, the
             * IAC SE was left off, or another option got inserted into the
             * suboption are all possibilities.  If we assume that the IAC was
             * not doubled, and really the IAC SE was left off, we could get
             * into an infinate loop here.  So, instead, we terminate the
             * suboption, and process the partial suboption if we can.
             */
            CURL_SB_ACCUM(tn, CURL_IAC);
            CURL_SB_ACCUM(tn, c);
            tn->subpointer -= 2;
            CURL_SB_TERM(tn);

            printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
            suboption(conn);   /* handle sub-option */
            tn->telrcv_state = CURL_TS_IAC;
            goto process_iac;
          }
          CURL_SB_ACCUM(tn,c);
          tn->telrcv_state = CURL_TS_SB;
        }
        else
        {
          CURL_SB_ACCUM(tn, CURL_IAC);
          CURL_SB_ACCUM(tn, CURL_SE);
          tn->subpointer -= 2;
          CURL_SB_TERM(tn);
          suboption(conn);   /* handle sub-option */
          tn->telrcv_state = CURL_TS_DATA;
        }
        break;
    }
  }
}
Exemple #6
0
void
sendayt(void)
{
    NET2ADD(IAC, AYT);
    printoption("SENT", IAC, AYT);
}
Exemple #7
0
void
sendeof(void)
{
    NET2ADD(IAC, xEOF);
    printoption("SENT", IAC, xEOF);
}
Exemple #8
0
void
xmitEC(void)
{
    NET2ADD(IAC, EC);
    printoption("SENT", IAC, EC);
}
Exemple #9
0
void
xmitEL(void)
{
    NET2ADD(IAC, EL);
    printoption("SENT", IAC, EL);
}
Exemple #10
0
static
CURLcode telrcv(struct connectdata *conn,
                const unsigned char *inbuf, /* Data received from socket */
                ssize_t count)              /* Number of bytes received */
{
  unsigned char c;
  CURLcode result;
  int in = 0;
  int startwrite=-1;
  struct SessionHandle *data = conn->data;
  struct TELNET *tn = (struct TELNET *)data->req.protop;

#define startskipping()                                       \
  if(startwrite >= 0) {                                       \
    result = Curl_client_write(conn,                          \
                               CLIENTWRITE_BODY,              \
                               (char *)&inbuf[startwrite],    \
                               in-startwrite);                \
    if(result)                                                \
      return result;                                          \
  }                                                           \
  startwrite = -1

#define writebyte() \
    if(startwrite < 0) \
      startwrite = in

#define bufferflush() startskipping()

  while(count--) {
    c = inbuf[in];

    switch (tn->telrcv_state) {
    case CURL_TS_CR:
      tn->telrcv_state = CURL_TS_DATA;
      if(c == '\0') {
        startskipping();
        break;   /* Ignore \0 after CR */
      }
      writebyte();
      break;

    case CURL_TS_DATA:
      if(c == CURL_IAC) {
        tn->telrcv_state = CURL_TS_IAC;
        startskipping();
        break;
      }
      else if(c == '\r')
        tn->telrcv_state = CURL_TS_CR;
      writebyte();
      break;

    case CURL_TS_IAC:
    process_iac:
      DEBUGASSERT(startwrite < 0);
      switch (c) {
      case CURL_WILL:
        tn->telrcv_state = CURL_TS_WILL;
        break;
      case CURL_WONT:
        tn->telrcv_state = CURL_TS_WONT;
        break;
      case CURL_DO:
        tn->telrcv_state = CURL_TS_DO;
        break;
      case CURL_DONT:
        tn->telrcv_state = CURL_TS_DONT;
        break;
      case CURL_SB:
        CURL_SB_CLEAR(tn);
        tn->telrcv_state = CURL_TS_SB;
        break;
      case CURL_IAC:
        tn->telrcv_state = CURL_TS_DATA;
        writebyte();
        break;
      case CURL_DM:
      case CURL_NOP:
      case CURL_GA:
      default:
        tn->telrcv_state = CURL_TS_DATA;
        printoption(data, "RCVD", CURL_IAC, c);
        break;
      }
      break;

      case CURL_TS_WILL:
        printoption(data, "RCVD", CURL_WILL, c);
        tn->please_negotiate = 1;
        rec_will(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_WONT:
        printoption(data, "RCVD", CURL_WONT, c);
        tn->please_negotiate = 1;
        rec_wont(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_DO:
        printoption(data, "RCVD", CURL_DO, c);
        tn->please_negotiate = 1;
        rec_do(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_DONT:
        printoption(data, "RCVD", CURL_DONT, c);
        tn->please_negotiate = 1;
        rec_dont(conn, c);
        tn->telrcv_state = CURL_TS_DATA;
        break;

      case CURL_TS_SB:
        if(c == CURL_IAC)
          tn->telrcv_state = CURL_TS_SE;
        else
          CURL_SB_ACCUM(tn, c);
        break;

      case CURL_TS_SE:
        if(c != CURL_SE) {
          if(c != CURL_IAC) {
            /*
             * This is an error.  We only expect to get "IAC IAC" or "IAC SE".
             * Several things may have happened.  An IAC was not doubled, the
             * IAC SE was left off, or another option got inserted into the
             * suboption are all possibilities.  If we assume that the IAC was
             * not doubled, and really the IAC SE was left off, we could get
             * into an infinate loop here.  So, instead, we terminate the
             * suboption, and process the partial suboption if we can.
             */
            CURL_SB_ACCUM(tn, CURL_IAC);
            CURL_SB_ACCUM(tn, c);
            tn->subpointer -= 2;
            CURL_SB_TERM(tn);

            printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
            suboption(conn);   /* handle sub-option */
            tn->telrcv_state = CURL_TS_IAC;
            goto process_iac;
          }
          CURL_SB_ACCUM(tn, c);
          tn->telrcv_state = CURL_TS_SB;
        }
        else
        {
          CURL_SB_ACCUM(tn, CURL_IAC);
          CURL_SB_ACCUM(tn, CURL_SE);
          tn->subpointer -= 2;
          CURL_SB_TERM(tn);
          suboption(conn);   /* handle sub-option */
          tn->telrcv_state = CURL_TS_DATA;
        }
        break;
    }
    ++in;
  }
  bufferflush();
  return CURLE_OK;
}
Exemple #11
0
void
telrcv()
{
    register int c;
    static int state = TS_DATA;
#if	defined(CRAY2) && defined(UNICOS5)
    char *opfrontp = pfrontp;
#endif

    while (ncc > 0) {
        if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
            break;
        c = *netip++ & 0377, ncc--;
        switch (state) {

        case TS_CR:
            state = TS_DATA;
            /* Strip off \n or \0 after a \r */
            if ((c == 0) || (c == '\n')) {
                break;
            }
        /* FALL THROUGH */

        case TS_DATA:
            if (c == IAC) {
                state = TS_IAC;
                break;
            }
            /*
             * We now map \r\n ==> \r for pragmatic reasons.
             * Many client implementations send \r\n when
             * the user hits the CarriageReturn key.
             *
             * We USED to map \r\n ==> \n, since \r\n says
             * that we want to be in column 1 of the next
             * printable line, and \n is the standard
             * unix way of saying that (\r is only good
             * if CRMOD is set, which it normally is).
             */
            if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) {
                int nc = *netip;
#ifdef	LINEMODE
                /*
                 * If we are operating in linemode,
                 * convert to local end-of-line.
                 */
                if (linemode && (ncc > 0) && (('\n' == nc) ||
                                              ((0 == nc) && tty_iscrnl())) ) {
                    netip++;
                    ncc--;
                    c = '\n';
                } else
#endif
                {
                    state = TS_CR;
                }
            }
            *pfrontp++ = c;
            break;

        case TS_IAC:
gotiac:
            switch (c) {

            /*
             * Send the process on the pty side an
             * interrupt.  Do this with a NULL or
             * interrupt char; depending on the tty mode.
             */
            case IP:
                DIAG(TD_OPTIONS,
                     printoption("td: recv IAC", c));
                interrupt();
                break;

            case BREAK:
                DIAG(TD_OPTIONS,
                     printoption("td: recv IAC", c));
                sendbrk();
                break;

            /*
             * Are You There?
             */
            case AYT:
                DIAG(TD_OPTIONS,
                     printoption("td: recv IAC", c));
                recv_ayt();
                break;

            /*
             * Abort Output
             */
            case AO:
            {
                DIAG(TD_OPTIONS,
                     printoption("td: recv IAC", c));
                ptyflush();	/* half-hearted */
                init_termbuf();

                if (slctab[SLC_AO].sptr &&
                        *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) {
                    *pfrontp++ =
                        (unsigned char)*slctab[SLC_AO].sptr;
                }

                netclear();	/* clear buffer back */
                *nfrontp++ = IAC;
                *nfrontp++ = DM;
                neturg = nfrontp-1; /* off by one XXX */
                DIAG(TD_OPTIONS,
                     printoption("td: send IAC", DM));
                break;
            }

            /*
             * Erase Character and
             * Erase Line
             */
            case EC:
            case EL:
            {
                cc_t ch;

                DIAG(TD_OPTIONS,
                     printoption("td: recv IAC", c));
                ptyflush();	/* half-hearted */
                init_termbuf();
                if (c == EC)
                    ch = *slctab[SLC_EC].sptr;
                else
                    ch = *slctab[SLC_EL].sptr;
                if (ch != (cc_t)(_POSIX_VDISABLE))
                    *pfrontp++ = (unsigned char)ch;
                break;
            }

            /*
             * Check for urgent data...
             */
            case DM:
                DIAG(TD_OPTIONS,
                     printoption("td: recv IAC", c));
                SYNCHing = stilloob(net);
                settimer(gotDM);
                break;


            /*
             * Begin option subnegotiation...
             */
            case SB:
                state = TS_SB;
                SB_CLEAR();
                continue;

            case WILL:
                state = TS_WILL;
                continue;

            case WONT:
                state = TS_WONT;
                continue;

            case DO:
                state = TS_DO;
                continue;

            case DONT:
                state = TS_DONT;
                continue;
            case EOR:
                if (his_state_is_will(TELOPT_EOR))
                    doeof();
                break;

            /*
             * Handle RFC 10xx Telnet linemode option additions
             * to command stream (EOF, SUSP, ABORT).
             */
            case xEOF:
                doeof();
                break;

            case SUSP:
                sendsusp();
                break;

            case ABORT:
                sendbrk();
                break;

            case IAC:
                *pfrontp++ = c;
                break;
            }
            state = TS_DATA;
            break;

        case TS_SB:
            if (c == IAC) {
                state = TS_SE;
            } else {
                SB_ACCUM(c);
            }
            break;

        case TS_SE:
            if (c != SE) {
                if (c != IAC) {
                    /*
                     * bad form of suboption negotiation.
                     * handle it in such a way as to avoid
                     * damage to local state.  Parse
                     * suboption buffer found so far,
                     * then treat remaining stream as
                     * another command sequence.
                     */

                    /* for DIAGNOSTICS */
                    SB_ACCUM(IAC);
                    SB_ACCUM(c);
                    subpointer -= 2;

                    SB_TERM();
                    suboption();
                    state = TS_IAC;
                    goto gotiac;
                }
                SB_ACCUM(c);
                state = TS_SB;
            } else {
                /* for DIAGNOSTICS */
                SB_ACCUM(IAC);
                SB_ACCUM(SE);
                subpointer -= 2;

                SB_TERM();
                suboption();	/* handle sub-option */
                state = TS_DATA;
            }
            break;

        case TS_WILL:
            willoption(c);
            state = TS_DATA;
            continue;

        case TS_WONT:
            wontoption(c);
            state = TS_DATA;
            continue;

        case TS_DO:
            dooption(c);
            state = TS_DATA;
            continue;

        case TS_DONT:
            dontoption(c);
            state = TS_DATA;
            continue;

        default:
            syslog(LOG_ERR, "telnetd: panic state=%d\n", state);
            printf("telnetd: panic state=%d\n", state);
            exit(1);
        }
    }
#if	defined(CRAY2) && defined(UNICOS5)
    if (!linemode) {
        char	xptyobuf[BUFSIZ+NETSLOP];
        char	xbuf2[BUFSIZ];
        register char *cp;
        int n = pfrontp - opfrontp, oc;
        memmove(xptyobuf, opfrontp, n);
        pfrontp = opfrontp;
        pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP,
                              xbuf2, &oc, BUFSIZ);
        for (cp = xbuf2; oc > 0; --oc)
            if ((*nfrontp++ = *cp++) == IAC)
                *nfrontp++ = IAC;
    }
#endif	/* defined(CRAY2) && defined(UNICOS5) */
}  /* end of telrcv */
Exemple #12
0
void dontoption(int option) {
    /*
     * Process client input.
     */
    DIAG(TD_OPTIONS, printoption("td: recv dont", option));

    if (will_wont_resp[option]) {
        will_wont_resp[option]--;
        if (will_wont_resp[option] && my_state_is_wont(option))
            will_wont_resp[option]--;
    }
    if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) {
        switch (option) {
        case TELOPT_BINARY:
            init_termbuf();
            tty_binaryout(0);
            set_termbuf();
            break;

        case TELOPT_ECHO:	/* we should stop echoing */
#ifdef	LINEMODE
#ifdef	KLUDGELINEMODE
            if (lmodetype == NO_LINEMODE)
#else
            if (his_state_is_wont(TELOPT_LINEMODE))
#endif
#endif
            {
                init_termbuf();
                tty_setecho(0);
                set_termbuf();
            }
            break;

        case TELOPT_SGA:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
            /*
             * If kludge linemode is in use, then we
             * must process an incoming do SGA for
             * linemode purposes.
             */
            if (lmodetype == KLUDGE_LINEMODE) {
                /*
                 * The client is asking us to turn
                 * linemode on.
                 */
                clientstat(TELOPT_LINEMODE, WILL, 0);
                /*
                 * If we did not turn line mode on,
                 * then what do we say?  Will SGA?
                 * This violates design of telnet.
                 * Gross.  Very Gross.
                 */
            }
            break;
#else
            set_my_want_state_wont(option);
            if (my_state_is_will(option))
                send_wont(option, 0);
            set_my_state_wont(option);
            if (turn_on_sga ^= 1) send_will(option,1);
            return;
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */

        default:
            break;
        }

        set_my_want_state_wont(option);
        if (my_state_is_will(option))
            send_wont(option, 0);
    }
    set_my_state_wont(option);
}
Exemple #13
0
void dooption(int option) {
    int changeok = 0;

    /*
     * Process client input.
     */

    DIAG(TD_OPTIONS, printoption("td: recv do", option));

    if (will_wont_resp[option]) {
        will_wont_resp[option]--;
        if (will_wont_resp[option] && my_state_is_will(option))
            will_wont_resp[option]--;
    }
    if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) {
        switch (option) {
        case TELOPT_ECHO:
#ifdef	LINEMODE
#ifdef	KLUDGELINEMODE
            if (lmodetype == NO_LINEMODE)
#else
            if (his_state_is_wont(TELOPT_LINEMODE))
#endif
#endif
            {
                init_termbuf();
                tty_setecho(1);
                set_termbuf();
            }
            changeok++;
            break;

        case TELOPT_BINARY:
            init_termbuf();
            tty_binaryout(1);
            set_termbuf();
            changeok++;
            break;

        case TELOPT_SGA:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
            /*
             * If kludge linemode is in use, then we must
             * process an incoming do SGA for linemode
             * purposes.
             */
            if (lmodetype == KLUDGE_LINEMODE) {
                /*
                 * Receipt of "do SGA" in kludge
                 * linemode is the peer asking us to
                 * turn off linemode.  Make note of
                 * the request.
                 */
                clientstat(TELOPT_LINEMODE, WONT, 0);
                /*
                 * If linemode did not get turned off
                 * then don't tell peer that we did.
                 * Breaking here forces a wont SGA to
                 * be returned.
                 */
                if (linemode)  break;
            }
#else
            turn_on_sga = 0;
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
            changeok++;
            break;

        case TELOPT_STATUS:
            changeok++;
            break;

        case TELOPT_TM:
            /*
             * Special case for TM.  We send a WILL, but
             * pretend we sent a WONT.
             */
            send_will(option, 0);
            set_my_want_state_wont(option);
            set_my_state_wont(option);
            return;

        case TELOPT_LOGOUT:
            /*
             * When we get a LOGOUT option, respond
             * with a WILL LOGOUT, make sure that
             * it gets written out to the network,
             * and then just go away...
             */
            set_my_want_state_will(TELOPT_LOGOUT);
            send_will(TELOPT_LOGOUT, 0);
            set_my_state_will(TELOPT_LOGOUT);
            (void)netflush();
            cleanup(0);
            /* NOT REACHED */
            break;

#if defined(ENCRYPT)
        case TELOPT_ENCRYPT:
            changeok++;
            break;
#endif
        case TELOPT_LINEMODE:
        case TELOPT_TTYPE:
        case TELOPT_NAWS:
        case TELOPT_TSPEED:
        case TELOPT_LFLOW:
        case TELOPT_XDISPLOC:
        case TELOPT_ENVIRON:
        default:
            break;
        }
        if (changeok) {
            set_my_want_state_will(option);
            send_will(option, 0);
        }
        else {
            will_wont_resp[option]++;
            send_wont(option, 0);
        }
    }
    set_my_state_will(option);
}
Exemple #14
0
void wontoption(int option) {
    /*
     * Process client input.
     */

    DIAG(TD_OPTIONS, printoption("td: recv wont", option));

    if (do_dont_resp[option]) {
        do_dont_resp[option]--;
        if (do_dont_resp[option] && his_state_is_wont(option))
            do_dont_resp[option]--;
    }
    if (do_dont_resp[option] == 0) {
        if (his_want_state_is_will(option)) {
            /* it is always ok to change to negative state */
            switch (option) {
            case TELOPT_ECHO:
                not42 = 1; /* doesn't seem to be a 4.2 system */
                break;

            case TELOPT_BINARY:
                init_termbuf();
                tty_binaryin(0);
                set_termbuf();
                break;

#ifdef LINEMODE
            case TELOPT_LINEMODE:
#ifdef KLUDGELINEMODE
                /*
                 * If real linemode is supported, then client is
                 * asking to turn linemode off.
                 */
                if (lmodetype != REAL_LINEMODE)
                    break;
                lmodetype = KLUDGE_LINEMODE;
# endif	/* KLUDGELINEMODE */
                clientstat(TELOPT_LINEMODE, WONT, 0);
                break;
#endif	/* LINEMODE */

            case TELOPT_TM:
                /*
                 * If we get a WONT TM, and had sent a DO TM,
                 * don't respond with a DONT TM, just leave it
                 * as is.  Short circut the state machine to
                 * achive this.
                 */
                set_his_want_state_wont(TELOPT_TM);
                return;

            case TELOPT_LFLOW:
                /*
                 * If we are not going to support flow control
                 * option, then let peer know that we can't
                 * change the flow control characters.
                 */
                slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE;
                slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE;
                break;

#if defined(AUTHENTICATE)
            case TELOPT_AUTHENTICATION:
                auth_finished(0, AUTH_REJECT);
                break;
#endif

            /*
             * For options that we might spin waiting for
             * sub-negotiation, if the client turns off the
             * option rather than responding to the request,
             * we have to treat it here as if we got a response
             * to the sub-negotiation, (by updating the timers)
             * so that we'll break out of the loop.
             */
            case TELOPT_TTYPE:
                settimer(ttypesubopt);
                break;

            case TELOPT_TSPEED:
                settimer(tspeedsubopt);
                break;

            case TELOPT_XDISPLOC:
                settimer(xdisplocsubopt);
                break;

            case TELOPT_ENVIRON:
                settimer(environsubopt);
                break;

            default:
                break;
            }
            set_his_want_state_wont(option);
            if (his_state_is_will(option)) send_dont(option, 0);
        }
        else {
            switch (option) {
            case TELOPT_TM:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
                if (lmodetype < REAL_LINEMODE) {
                    lmodetype = NO_LINEMODE;
                    clientstat(TELOPT_LINEMODE, WONT, 0);
                    send_will(TELOPT_SGA, 1);
                    send_will(TELOPT_ECHO, 1);
                }
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
                break;

#if	defined(AUTHENTICATE)
            case TELOPT_AUTHENTICATION:
                auth_finished(0, AUTH_REJECT);
                break;
#endif
            default:
                break;
            }
        }
    }
}  /* end of wontoption */
Exemple #15
0
void willoption(int option) {
    int changeok = 0;
    void (*func)(void) = 0;

    /*
     * process input from peer.
     */

    DIAG(TD_OPTIONS, printoption("td: recv will", option));

    if (do_dont_resp[option]) {
        do_dont_resp[option]--;
        if (do_dont_resp[option] && his_state_is_will(option))
            do_dont_resp[option]--;
    }
    if (do_dont_resp[option] == 0) {
        if (his_want_state_is_wont(option)) {
            switch (option) {

            case TELOPT_BINARY:
                init_termbuf();
                tty_binaryin(1);
                set_termbuf();
                changeok++;
                break;

            case TELOPT_ECHO:
                /*
                 * See comments below for more info.
                 */
                not42 = 0;	/* looks like a 4.2 system */
                break;

            case TELOPT_TM:
#if defined(LINEMODE) && defined(KLUDGELINEMODE)
                /*
                 * This telnetd implementation does not really
                 * support timing marks, it just uses them to
                 * support the kludge linemode stuff.  If we
                 * receive a will or wont TM in response to our
                 * do TM request that may have been sent to
                 * determine kludge linemode support, process
                 * it, otherwise TM should get a negative
                 * response back.
                 */
                /*
                 * Handle the linemode kludge stuff.
                 * If we are not currently supporting any
                 * linemode at all, then we assume that this
                 * is the client telling us to use kludge
                 * linemode in response to our query.  Set the
                 * linemode type that is to be supported, note
                 * that the client wishes to use linemode, and
                 * eat the will TM as though it never arrived.
                 */
                if (lmodetype < KLUDGE_LINEMODE) {
                    lmodetype = KLUDGE_LINEMODE;
                    clientstat(TELOPT_LINEMODE, WILL, 0);
                    send_wont(TELOPT_SGA, 1);
                }
#endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
                /*
                 * We never respond to a WILL TM, and
                 * we leave the state WONT.
                 */
                return;

            case TELOPT_LFLOW:
                /*
                 * If we are going to support flow control
                 * option, then don't worry peer that we can't
                 * change the flow control characters.
                 */
                slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XON].defset.flag |= SLC_DEFAULT;
                slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS;
                slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT;
            case TELOPT_TTYPE:
            case TELOPT_SGA:
            case TELOPT_NAWS:
            case TELOPT_TSPEED:
            case TELOPT_XDISPLOC:
            case TELOPT_ENVIRON:
                changeok++;
                break;

#ifdef LINEMODE
            case TELOPT_LINEMODE:
#ifdef KLUDGELINEMODE
                /*
                 * Note client's desire to use linemode.
                 */
                lmodetype = REAL_LINEMODE;
#endif	/* KLUDGELINEMODE */
                func = doclientstat;
                changeok++;
                break;
#endif	/* LINEMODE */

#ifdef	AUTHENTICATE
            case TELOPT_AUTHENTICATION:
                func = auth_request;
                changeok++;
                break;
#endif

#ifdef ENCRYPT
            case TELOPT_ENCRYPT:
                func = encrypt_send_support;
                changeok++;
                break;
#endif

            default:
                break;
            }
            if (changeok) {
                set_his_want_state_will(option);
                send_do(option, 0);
            }
            else {
                do_dont_resp[option]++;
                send_dont(option, 0);
            }
        }
        else {
            /*
             * Option processing that should happen when
             * we receive conformation of a change in
             * state that we had requested.
             */
            switch (option) {
            case TELOPT_ECHO:
                not42 = 0;	/* looks like a 4.2 system */
                /*
                 * Egads, he responded "WILL ECHO".  Turn
                 * it off right now!
                 */
                send_dont(option, 1);
                /*
                 * "WILL ECHO".  Kludge upon kludge!
                 * A 4.2 client is now echoing user input at
                 * the tty.  This is probably undesireable and
                 * it should be stopped.  The client will
                 * respond WONT TM to the DO TM that we send to
                 * check for kludge linemode.  When the WONT TM
                 * arrives, linemode will be turned off and a
                 * change propogated to the pty.  This change
                 * will cause us to process the new pty state
                 * in localstat(), which will notice that
                 * linemode is off and send a WILL ECHO
                 * so that we are properly in character mode and
                 * all is well.
                 */
                break;
#ifdef	LINEMODE
            case TELOPT_LINEMODE:
# ifdef	KLUDGELINEMODE
                /*
                 * Note client's desire to use linemode.
                 */
                lmodetype = REAL_LINEMODE;
# endif	/* KLUDGELINEMODE */
                func = doclientstat;
                break;
#endif	/* LINEMODE */

#ifdef	AUTHENTICATE
            case TELOPT_AUTHENTICATION:
                func = auth_request;
                break;
#endif

#ifdef	ENCRYPT
            case TELOPT_ENCRYPT:
                func = encrypt_send_support;
                break;
#endif
            }
        }
    }
    set_his_state_will(option);
    if (func) (*func)();
}