version 1.3, 1997/06/05 01:07:39 |
version 1.4, 1998/03/12 04:57:43 |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
#ifndef lint |
#include "telnet_locl.h" |
#if 0 |
|
static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; |
|
static char rcsid[] = "$NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $"; |
|
#else |
|
static char rcsid[] = "$OpenBSD$"; |
|
#endif |
|
#endif /* not lint */ |
|
|
|
#include <sys/types.h> |
#define strip(x) (eight ? (x) : ((x) & 0x7f)) |
|
|
#if defined(unix) |
|
#include <signal.h> |
|
/* By the way, we need to include curses.h before telnet.h since, |
|
* among other things, telnet.h #defines 'DO', which is a variable |
|
* declared in curses.h. |
|
*/ |
|
#endif /* defined(unix) */ |
|
|
|
#include <arpa/telnet.h> |
|
|
|
#include <ctype.h> |
|
|
|
#include "ring.h" |
|
|
|
#include "defines.h" |
|
#include "externs.h" |
|
#include "types.h" |
|
#include "general.h" |
|
|
|
|
|
#define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) |
|
|
|
static unsigned char subbuffer[SUBBUFSIZE], |
static unsigned char subbuffer[SUBBUFSIZE], |
*subpointer, *subend; /* buffer for sub-options */ |
*subpointer, *subend; /* buffer for sub-options */ |
#define SB_CLEAR() subpointer = subbuffer; |
#define SB_CLEAR() subpointer = subbuffer; |
|
|
char will_wont_resp[256]; |
char will_wont_resp[256]; |
|
|
int |
int |
eight = 0, |
eight = 3, |
|
binary = 0, |
autologin = 0, /* Autologin anyone? */ |
autologin = 0, /* Autologin anyone? */ |
skiprc = 0, |
skiprc = 0, |
connected, |
connected, |
|
|
*/ |
*/ |
|
|
Clocks clocks; |
Clocks clocks; |
|
|
#ifdef notdef |
|
Modelist modelist[] = { |
|
{ "telnet command mode", COMMAND_LINE }, |
|
{ "character-at-a-time mode", 0 }, |
|
{ "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, |
|
{ "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, |
|
{ "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, |
|
{ "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, |
|
{ "3270 mode", 0 }, |
|
}; |
|
#endif |
|
|
|
|
|
/* |
/* |
|
|
env_init(); |
env_init(); |
|
|
SB_CLEAR(); |
SB_CLEAR(); |
ClearArray(options); |
memset((char *)options, 0, sizeof options); |
|
|
connected = In3270 = ISend = localflow = donebinarytoggle = 0; |
connected = In3270 = ISend = localflow = donebinarytoggle = 0; |
#if defined(AUTHENTICATION) |
#if defined(AUTHENTICATION) || defined(ENCRYPTION) |
auth_encrypt_connect(connected); |
auth_encrypt_connect(connected); |
#endif /* defined(AUTHENTICATION) */ |
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ |
restartany = -1; |
restartany = -1; |
|
|
SYNCHing = 0; |
SYNCHing = 0; |
|
|
} |
} |
|
|
|
|
#ifdef notdef |
|
#include <varargs.h> |
|
|
|
/*VARARGS*/ |
|
static void |
|
printring(va_alist) |
|
va_dcl |
|
{ |
|
va_list ap; |
|
char buffer[100]; /* where things go */ |
|
char *ptr; |
|
char *format; |
|
char *string; |
|
Ring *ring; |
|
int i; |
|
|
|
va_start(ap); |
|
|
|
ring = va_arg(ap, Ring *); |
|
format = va_arg(ap, char *); |
|
ptr = buffer; |
|
|
|
while ((i = *format++) != 0) { |
|
if (i == '%') { |
|
i = *format++; |
|
switch (i) { |
|
case 'c': |
|
*ptr++ = va_arg(ap, int); |
|
break; |
|
case 's': |
|
string = va_arg(ap, char *); |
|
ring_supply_data(ring, buffer, ptr-buffer); |
|
ring_supply_data(ring, string, strlen(string)); |
|
ptr = buffer; |
|
break; |
|
case 0: |
|
ExitString("printring: trailing %%.\n", 1); |
|
/*NOTREACHED*/ |
|
default: |
|
ExitString("printring: unknown format character.\n", 1); |
|
/*NOTREACHED*/ |
|
} |
|
} else { |
|
*ptr++ = i; |
|
} |
|
} |
|
ring_supply_data(ring, buffer, ptr-buffer); |
|
} |
|
#endif |
|
|
|
/* |
/* |
* These routines are in charge of sending option negotiations |
* These routines are in charge of sending option negotiations |
* to the other side. |
* to the other side. |
|
|
#if defined(AUTHENTICATION) |
#if defined(AUTHENTICATION) |
case TELOPT_AUTHENTICATION: |
case TELOPT_AUTHENTICATION: |
#endif |
#endif |
|
#if defined(ENCRYPTION) |
|
case TELOPT_ENCRYPT: |
|
#endif |
new_state_ok = 1; |
new_state_ok = 1; |
break; |
break; |
|
|
|
|
} |
} |
} |
} |
set_my_state_do(option); |
set_my_state_do(option); |
|
#if defined(ENCRYPTION) |
|
if (option == TELOPT_ENCRYPT) |
|
encrypt_send_support(); |
|
#endif |
|
|
} |
} |
|
|
void |
void |
|
|
set_my_state_dont(option); |
set_my_state_dont(option); |
return; /* Never reply to TM will's/wont's */ |
return; /* Never reply to TM will's/wont's */ |
|
|
|
#ifdef ENCRYPTION |
|
case TELOPT_ENCRYPT: |
|
encrypt_not(); |
|
break; |
|
#endif |
default: |
default: |
break; |
break; |
} |
} |
|
|
case TELOPT_LFLOW: /* local flow control */ |
case TELOPT_LFLOW: /* local flow control */ |
case TELOPT_TTYPE: /* terminal type option */ |
case TELOPT_TTYPE: /* terminal type option */ |
case TELOPT_SGA: /* no big deal */ |
case TELOPT_SGA: /* no big deal */ |
|
#if defined(ENCRYPTION) |
|
case TELOPT_ENCRYPT: /* encryption variable option */ |
|
#endif |
new_state_ok = 1; |
new_state_ok = 1; |
break; |
break; |
|
|
|
|
* Skip entries with spaces or non-ascii values. |
* Skip entries with spaces or non-ascii values. |
* Convert lower case letters to upper case. |
* Convert lower case letters to upper case. |
*/ |
*/ |
if ((c == ' ') || !isascii(c)) |
#define ISASCII(c) (!((c)&0x80)) |
|
if ((c == ' ') || !ISASCII(c)) |
n = 1; |
n = 1; |
else if (islower(c)) |
else if (islower(c)) |
*cp = toupper(c); |
*cp = toupper(c); |
|
|
return (1); |
return (1); |
} |
} |
|
|
#ifdef TERMCAP |
static char termbuf[1024]; |
char termbuf[1024]; |
|
|
|
/*ARGSUSED*/ |
/*ARGSUSED*/ |
int |
int |
setupterm(tname, fd, errp) |
telnet_setupterm(tname, fd, errp) |
char *tname; |
char *tname; |
int fd, *errp; |
int fd, *errp; |
{ |
{ |
|
|
*errp = 0; |
*errp = 0; |
return(-1); |
return(-1); |
} |
} |
#else |
|
#define termbuf ttytype |
|
extern char ttytype[]; |
|
#endif |
|
|
|
int resettermname = 1; |
int resettermname = 1; |
|
|
|
|
if (tnamep && tnamep != unknown) |
if (tnamep && tnamep != unknown) |
free(tnamep); |
free(tnamep); |
if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && |
if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && |
(setupterm(tname, 1, &err) == 0)) { |
(telnet_setupterm(tname, 1, &err) == 0)) { |
tnamep = mklist(termbuf, tname); |
tnamep = mklist(termbuf, tname); |
} else { |
} else { |
if (tname && ((int)strlen(tname) <= 40)) { |
if (tname && ((int)strlen(tname) <= 40)) { |
|
|
name = gettermname(); |
name = gettermname(); |
len = strlen(name) + 4 + 2; |
len = strlen(name) + 4 + 2; |
if (len < NETROOM()) { |
if (len < NETROOM()) { |
sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, |
snprintf((char *)temp, sizeof(temp), |
TELQUAL_IS, name, IAC, SE); |
"%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, |
|
TELQUAL_IS, name, IAC, SE); |
ring_supply_data(&netoring, temp, len); |
ring_supply_data(&netoring, temp, len); |
printsub('>', &temp[2], len-2); |
printsub('>', &temp[2], len-2); |
} else { |
} else { |
|
|
|
|
TerminalSpeeds(&ispeed, &ospeed); |
TerminalSpeeds(&ispeed, &ospeed); |
|
|
sprintf((char *)temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED, |
snprintf((char *)temp, sizeof(temp), |
TELQUAL_IS, ospeed, ispeed, IAC, SE); |
"%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED, |
|
TELQUAL_IS, ospeed, ispeed, IAC, SE); |
len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ |
len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ |
|
|
if (len < NETROOM()) { |
if (len < NETROOM()) { |
|
|
send_wont(TELOPT_XDISPLOC, 1); |
send_wont(TELOPT_XDISPLOC, 1); |
break; |
break; |
} |
} |
sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, |
snprintf((char *)temp, sizeof(temp), |
|
"%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, |
TELQUAL_IS, dp, IAC, SE); |
TELQUAL_IS, dp, IAC, SE); |
len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ |
len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ |
|
|
|
|
} |
} |
break; |
break; |
#endif |
#endif |
|
#if defined(ENCRYPTION) |
|
case TELOPT_ENCRYPT: |
|
if (SB_EOF()) |
|
return; |
|
switch(SB_GET()) { |
|
case ENCRYPT_START: |
|
if (my_want_state_is_dont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_start(subpointer, SB_LEN()); |
|
break; |
|
case ENCRYPT_END: |
|
if (my_want_state_is_dont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_end(); |
|
break; |
|
case ENCRYPT_SUPPORT: |
|
if (my_want_state_is_wont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_support(subpointer, SB_LEN()); |
|
break; |
|
case ENCRYPT_REQSTART: |
|
if (my_want_state_is_wont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_request_start(subpointer, SB_LEN()); |
|
break; |
|
case ENCRYPT_REQEND: |
|
if (my_want_state_is_wont(TELOPT_ENCRYPT)) |
|
return; |
|
/* |
|
* We can always send an REQEND so that we cannot |
|
* get stuck encrypting. We should only get this |
|
* if we have been able to get in the correct mode |
|
* anyhow. |
|
*/ |
|
encrypt_request_end(); |
|
break; |
|
case ENCRYPT_IS: |
|
if (my_want_state_is_dont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_is(subpointer, SB_LEN()); |
|
break; |
|
case ENCRYPT_REPLY: |
|
if (my_want_state_is_wont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_reply(subpointer, SB_LEN()); |
|
break; |
|
case ENCRYPT_ENC_KEYID: |
|
if (my_want_state_is_dont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_enc_keyid(subpointer, SB_LEN()); |
|
break; |
|
case ENCRYPT_DEC_KEYID: |
|
if (my_want_state_is_wont(TELOPT_ENCRYPT)) |
|
return; |
|
encrypt_dec_keyid(subpointer, SB_LEN()); |
|
break; |
|
default: |
|
break; |
|
} |
|
break; |
|
#endif |
default: |
default: |
break; |
break; |
} |
} |
|
|
|
|
#define initfunc(func, flags) { \ |
#define initfunc(func, flags) { \ |
spcp = &spc_data[func]; \ |
spcp = &spc_data[func]; \ |
if (spcp->valp = tcval(func)) { \ |
if ((spcp->valp = tcval(func))) { \ |
spcp->val = *spcp->valp; \ |
spcp->val = *spcp->valp; \ |
spcp->mylevel = SLC_VARIABLE|flags; \ |
spcp->mylevel = SLC_VARIABLE|flags; \ |
} else { \ |
} else { \ |
|
|
if (ep == NULL || *ep == '\0') { |
if (ep == NULL || *ep == '\0') { |
/* Send user defined variables first. */ |
/* Send user defined variables first. */ |
env_default(1, 0); |
env_default(1, 0); |
while (ep = env_default(0, 0)) |
while ((ep = env_default(0, 0))) |
env_opt_add(ep); |
env_opt_add(ep); |
|
|
/* Now add the list of well know variables. */ |
/* Now add the list of well know variables. */ |
env_default(1, 1); |
env_default(1, 1); |
while (ep = env_default(0, 1)) |
while ((ep = env_default(0, 1))) |
env_opt_add(ep); |
env_opt_add(ep); |
return; |
return; |
} |
} |
|
|
opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); |
opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); |
opt_replyend = opt_reply + len; |
opt_replyend = opt_reply + len; |
} |
} |
if (opt_welldefined(ep)) |
if (opt_welldefined((char *)ep)) |
#ifdef OLD_ENVIRON |
#ifdef OLD_ENVIRON |
if (telopt_environ == TELOPT_OLD_ENVIRON) |
if (telopt_environ == TELOPT_OLD_ENVIRON) |
*opt_replyp++ = old_env_var; |
*opt_replyp++ = old_env_var; |
|
|
else |
else |
*opt_replyp++ = ENV_USERVAR; |
*opt_replyp++ = ENV_USERVAR; |
for (;;) { |
for (;;) { |
while (c = *ep++) { |
while ((c = *ep++)) { |
switch(c&0xff) { |
switch(c&0xff) { |
case IAC: |
case IAC: |
*opt_replyp++ = IAC; |
*opt_replyp++ = IAC; |
|
|
} |
} |
*opt_replyp++ = c; |
*opt_replyp++ = c; |
} |
} |
if (ep = vp) { |
if ((ep = vp)) { |
#ifdef OLD_ENVIRON |
#ifdef OLD_ENVIRON |
if (telopt_environ == TELOPT_OLD_ENVIRON) |
if (telopt_environ == TELOPT_OLD_ENVIRON) |
*opt_replyp++ = old_env_value; |
*opt_replyp++ = old_env_value; |
|
|
} |
} |
|
|
c = *sbp++ & 0xff, scc--; count++; |
c = *sbp++ & 0xff, scc--; count++; |
|
#if defined(ENCRYPTION) |
|
if (decrypt_input) |
|
c = (*decrypt_input)(c); |
|
#endif |
|
|
switch (telrcv_state) { |
switch (telrcv_state) { |
|
|
|
|
# endif /* defined(TN3270) */ |
# endif /* defined(TN3270) */ |
/* |
/* |
* The 'crmod' hack (see following) is needed |
* The 'crmod' hack (see following) is needed |
* since we can't * set CRMOD on output only. |
* since we can't set CRMOD on output only. |
* Machines like MULTICS like to send \r without |
* Machines like MULTICS like to send \r without |
* \n; since we must turn off CRMOD to get proper |
* \n; since we must turn off CRMOD to get proper |
* input, the mapping is done here (sigh). |
* input, the mapping is done here (sigh). |
|
|
if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { |
if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { |
if (scc > 0) { |
if (scc > 0) { |
c = *sbp&0xff; |
c = *sbp&0xff; |
|
#if defined(ENCRYPTION) |
|
if (decrypt_input) |
|
c = (*decrypt_input)(c); |
|
#endif |
if (c == 0) { |
if (c == 0) { |
sbp++, scc--; count++; |
sbp++, scc--; count++; |
/* a "true" CR */ |
/* a "true" CR */ |
|
|
sbp++, scc--; count++; |
sbp++, scc--; count++; |
TTYADD('\n'); |
TTYADD('\n'); |
} else { |
} else { |
|
#if defined(ENCRYPTION) |
|
if (decrypt_input) |
|
(*decrypt_input)(-1); |
|
#endif |
TTYADD('\r'); |
TTYADD('\r'); |
if (crmod) { |
if (crmod) { |
TTYADD('\n'); |
TTYADD('\n'); |
|
|
{ |
{ |
sys_telnet_init(); |
sys_telnet_init(); |
|
|
#if defined(AUTHENTICATION) |
#if defined(AUTHENTICATION) || defined(ENCRYPTION) |
{ |
{ |
static char local_host[256] = { 0 }; |
static char local_host[256] = { 0 }; |
|
|
|
|
auth_encrypt_init(local_host, hostname, "TELNET", 0); |
auth_encrypt_init(local_host, hostname, "TELNET", 0); |
auth_encrypt_user(user); |
auth_encrypt_user(user); |
} |
} |
#endif /* defined(AUTHENTICATION) */ |
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ |
# if !defined(TN3270) |
# if !defined(TN3270) |
if (telnetport) { |
if (telnetport) { |
#if defined(AUTHENTICATION) |
#if defined(AUTHENTICATION) |
if (autologin) |
if (autologin) |
send_will(TELOPT_AUTHENTICATION, 1); |
send_will(TELOPT_AUTHENTICATION, 1); |
#endif |
#endif |
|
#if defined(ENCRYPTION) |
|
send_do(TELOPT_ENCRYPT, 1); |
|
send_will(TELOPT_ENCRYPT, 1); |
|
#endif |
send_do(TELOPT_SGA, 1); |
send_do(TELOPT_SGA, 1); |
send_will(TELOPT_TTYPE, 1); |
send_will(TELOPT_TTYPE, 1); |
send_will(TELOPT_NAWS, 1); |
send_will(TELOPT_NAWS, 1); |
|
|
send_do(TELOPT_STATUS, 1); |
send_do(TELOPT_STATUS, 1); |
if (env_getvalue((unsigned char *)"DISPLAY")) |
if (env_getvalue((unsigned char *)"DISPLAY")) |
send_will(TELOPT_XDISPLOC, 1); |
send_will(TELOPT_XDISPLOC, 1); |
if (eight) |
if (binary) |
tel_enter_binary(eight); |
tel_enter_binary(binary); |
} |
} |
# endif /* !defined(TN3270) */ |
# endif /* !defined(TN3270) */ |
|
|