aboutsummaryrefslogtreecommitdiff
path: root/src/appl/telnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/appl/telnet')
-rw-r--r--src/appl/telnet/libtelnet/ChangeLog38
-rw-r--r--src/appl/telnet/libtelnet/configure.in8
-rw-r--r--src/appl/telnet/libtelnet/gettytab.c5
-rw-r--r--src/appl/telnet/libtelnet/kerberos.c16
-rw-r--r--src/appl/telnet/libtelnet/kerberos5.c51
-rw-r--r--src/appl/telnet/libtelnet/setenv.c6
-rw-r--r--src/appl/telnet/libtelnet/spx.c20
-rw-r--r--src/appl/telnet/telnet/ChangeLog15
-rw-r--r--src/appl/telnet/telnet/commands.c15
-rw-r--r--src/appl/telnet/telnet/externs.h2
-rw-r--r--src/appl/telnet/telnet/main.c3
-rw-r--r--src/appl/telnet/telnet/tn3270.c7
-rw-r--r--src/appl/telnet/telnet/utilities.c6
-rw-r--r--src/appl/telnet/telnetd/ChangeLog67
-rw-r--r--src/appl/telnet/telnetd/authenc.c17
-rw-r--r--src/appl/telnet/telnetd/configure.in2
-rw-r--r--src/appl/telnet/telnetd/ext.h9
-rw-r--r--src/appl/telnet/telnetd/slc.c2
-rw-r--r--src/appl/telnet/telnetd/state.c39
-rw-r--r--src/appl/telnet/telnetd/sys_term.c1
-rw-r--r--src/appl/telnet/telnetd/telnetd-ktd.c53
-rw-r--r--src/appl/telnet/telnetd/telnetd.c74
-rw-r--r--src/appl/telnet/telnetd/termstat.c20
-rw-r--r--src/appl/telnet/telnetd/utility.c682
24 files changed, 663 insertions, 495 deletions
diff --git a/src/appl/telnet/libtelnet/ChangeLog b/src/appl/telnet/libtelnet/ChangeLog
index 67877b1..95906f3 100644
--- a/src/appl/telnet/libtelnet/ChangeLog
+++ b/src/appl/telnet/libtelnet/ChangeLog
@@ -1,3 +1,41 @@
+2003-04-01 Nalin Dahyabhai <nalin@redhat.com>
+
+ * kerberos5.c (kerberos5_is): Check principal name length before
+ examining components.
+
+2002-03-29 Tom Yu <tlyu@mit.edu>
+
+ * kerberos5.c, kerberos.c (Data): Don't overflow
+ buffer. [telnet/1073] [pullup and reindent from trunk]
+
+2001-02-21 Tom Yu <tlyu@mit.edu>
+
+ * configure.in: Check for setenv, unsetenv, and getenv. Compile
+ setenv.c if at least of these is undefined.
+
+ * setenv.c: Add conditionals for compilation of setenv, unsetenv,
+ and getenv such that they only get compiled if they don't already
+ exist.
+
+2000-05-11 Nalin Dahyabhai <nalin@redhat.com>
+
+ * gettytab.c (nchktc): Don't overflow tcname if tty type name is too
+ long
+ * kerberos.c (kerberos4_status): Make sure "UserNameRequested" is
+ always properly terminated.
+ * kerberos5.c (kerberos5_is): If bad principal name is too long to fit
+ in "errbuf", don't print it.
+ (kerberos5_status): Make sure "UserNameRequested" is always properly
+ terminated.
+ * spx.c (spx_status): Ditto.
+
+2000-04-28 Nalin Dahyabhai <nalin@redhat.com>
+
+ * kerberos5.c (kerberos5_is): Don't overflow buffer "errbuf".
+ * spx.c (spx_init, spx_send, spx_is): Don't overflow buffer
+ "targ_printable".
+ (spx_status): Don't overflow buffer "acl_file".
+
1999-10-26 Tom Yu <tlyu@mit.edu>
* Makefile.in: Clean up usage of CFLAGS, CPPFLAGS, DEFS, DEFINES,
diff --git a/src/appl/telnet/libtelnet/configure.in b/src/appl/telnet/libtelnet/configure.in
index 3bae866..9040a98 100644
--- a/src/appl/telnet/libtelnet/configure.in
+++ b/src/appl/telnet/libtelnet/configure.in
@@ -3,10 +3,14 @@ CONFIG_RULES
AC_PROG_ARCHIVE
AC_PROG_ARCHIVE_ADD
AC_PROG_RANLIB
-AC_REPLACE_FUNCS([strcasecmp strdup setenv setsid strerror strftime getopt herror parsetos])
-AC_CHECK_FUNCS(gettosbyname cgetent)
+AC_REPLACE_FUNCS([strcasecmp strdup setsid strerror strftime getopt herror parsetos])
+AC_CHECK_FUNCS(setenv unsetenv getenv gettosbyname cgetent)
AC_CHECK_HEADERS(stdlib.h string.h)
LIBOBJS="$LIBOBJS getent.o"
+if test $ac_cv_func_setenv = no || test $ac_cv_func_unsetenv = no \
+ || test $ac_cv_func_getenv = no; then
+ LIBOBJS="$LIBOBJS setenv.o"
+fi
AC_CONST
if test "$KRB4_LIB" = ''; then
AC_MSG_RESULT(No Kerberos 4 authentication)
diff --git a/src/appl/telnet/libtelnet/gettytab.c b/src/appl/telnet/libtelnet/gettytab.c
index f6ffb7c..aaad43a 100644
--- a/src/appl/telnet/libtelnet/gettytab.c
+++ b/src/appl/telnet/libtelnet/gettytab.c
@@ -98,9 +98,10 @@ nchktc()
/* p now points to beginning of last field */
if (p[0] != 't' || p[1] != 'c')
return(1);
- strcpy(tcname,p+3);
+ strncpy(tcname, p + 3, sizeof(tcname) - 1);
+ tcname[sizeof(tcname) - 1] = '\0';
q = tcname;
- while (q && *q != ':')
+ while (*q && *q != ':')
q++;
*q = 0;
if (++hopcount > MAXHOP) {
diff --git a/src/appl/telnet/libtelnet/kerberos.c b/src/appl/telnet/libtelnet/kerberos.c
index 734466e..0fda99b 100644
--- a/src/appl/telnet/libtelnet/kerberos.c
+++ b/src/appl/telnet/libtelnet/kerberos.c
@@ -141,6 +141,7 @@ Data(ap, type, d, c)
{
unsigned char *p = str_data + 4;
unsigned char *cd = (unsigned char *)d;
+ size_t spaceleft = sizeof(str_data) - 4;
if (c == -1)
c = strlen((char *)cd);
@@ -156,9 +157,16 @@ Data(ap, type, d, c)
*p++ = ap->type;
*p++ = ap->way;
*p++ = type;
+ spaceleft -= 3;
while (c-- > 0) {
- if ((*p++ = *cd++) == IAC)
- *p++ = IAC;
+ if ((*p++ = *cd++) == IAC) {
+ *p++ = IAC;
+ spaceleft--;
+ }
+ if ((--spaceleft < 4) && c) {
+ errno = ENOMEM;
+ return -1;
+ }
}
*p++ = IAC;
*p++ = SE;
@@ -602,7 +610,9 @@ kerberos4_status(ap, name, level)
return(level);
if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
- strcpy(name, UserNameRequested);
+ /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+ strncpy(name, UserNameRequested, 255);
+ name[255] = '\0';
return(AUTH_VALID);
} else
return(AUTH_USER);
diff --git a/src/appl/telnet/libtelnet/kerberos5.c b/src/appl/telnet/libtelnet/kerberos5.c
index 6a62f36..b9bbae8 100644
--- a/src/appl/telnet/libtelnet/kerberos5.c
+++ b/src/appl/telnet/libtelnet/kerberos5.c
@@ -95,7 +95,7 @@ void kerberos5_forward();
#endif /* FORWARD */
-static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
+static unsigned char str_data[8192] = {IAC, SB, TELOPT_AUTHENTICATION, 0,
AUTHTYPE_KERBEROS_V5, };
/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
TELQUAL_NAME, };*/
@@ -136,6 +136,7 @@ Data(ap, type, d, c)
{
unsigned char *p = str_data + 4;
unsigned char *cd = (unsigned char *)d;
+ size_t spaceleft = sizeof(str_data) - 4;
if (c == -1)
c = strlen((char *)cd);
@@ -151,9 +152,16 @@ Data(ap, type, d, c)
*p++ = ap->type;
*p++ = ap->way;
*p++ = type;
+ spaceleft -= 3;
while (c-- > 0) {
- if ((*p++ = *cd++) == IAC)
- *p++ = IAC;
+ if ((*p++ = *cd++) == IAC) {
+ *p++ = IAC;
+ spaceleft--;
+ }
+ if ((--spaceleft < 4) && c) {
+ errno = ENOMEM;
+ return -1;
+ }
}
*p++ = IAC;
*p++ = SE;
@@ -423,7 +431,8 @@ kerberos5_is(ap, data, cnt)
NULL, keytabid, NULL, &ticket);
if (r) {
(void) strcpy(errbuf, "krb5_rd_req failed: ");
- (void) strcat(errbuf, error_message(r));
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
goto errout;
}
@@ -432,6 +441,10 @@ kerberos5_is(ap, data, cnt)
* first component of a service name especially since
* the default is of length 4.
*/
+ if (krb5_princ_size(telnet_context,ticket->server) < 1) {
+ (void) strcpy(errbuf, "malformed service name");
+ goto errout;
+ }
if (krb5_princ_component(telnet_context,ticket->server,0)->length < 256) {
char princ[256];
strncpy(princ,
@@ -440,8 +453,12 @@ kerberos5_is(ap, data, cnt)
princ[krb5_princ_component(telnet_context,
ticket->server,0)->length] = '\0';
if (strcmp("host", princ)) {
- (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"%s\"",
- princ, "host");
+ if(strlen(princ) < sizeof(errbuf) - 39) {
+ (void) sprintf(errbuf, "incorrect service name: \"%s\" != \"host\"",
+ princ);
+ } else {
+ (void) sprintf(errbuf, "incorrect service name: principal != \"host\"");
+ }
goto errout;
}
} else {
@@ -455,7 +472,8 @@ kerberos5_is(ap, data, cnt)
if (r) {
(void) strcpy(errbuf,
"krb5_auth_con_getauthenticator failed: ");
- (void) strcat(errbuf, error_message(r));
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
goto errout;
}
if ((ap->way & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON &&
@@ -476,7 +494,8 @@ kerberos5_is(ap, data, cnt)
&key);
if (r) {
(void) strcpy(errbuf, "krb5_auth_con_getkey failed: ");
- (void) strcat(errbuf, error_message(r));
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
goto errout;
}
r = krb5_verify_checksum(telnet_context,
@@ -495,7 +514,8 @@ kerberos5_is(ap, data, cnt)
if (r) {
(void) strcpy(errbuf,
"checksum verification failed: ");
- (void) strcat(errbuf, error_message(r));
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
goto errout;
}
krb5_free_keyblock(telnet_context, key);
@@ -506,7 +526,8 @@ kerberos5_is(ap, data, cnt)
if ((r = krb5_mk_rep(telnet_context, auth_context,
&outbuf))) {
(void) strcpy(errbuf, "Make reply failed: ");
- (void) strcat(errbuf, error_message(r));
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
goto errout;
}
@@ -560,7 +581,8 @@ kerberos5_is(ap, data, cnt)
char errbuf[128];
(void) strcpy(errbuf, "Read forwarded creds failed: ");
- (void) strcat(errbuf, error_message(r));
+ errbuf[sizeof(errbuf) - 1] = '\0';
+ (void) strncat(errbuf, error_message(r), sizeof(errbuf) - 1 - strlen(errbuf));
Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
if (auth_debug_mode)
printf(
@@ -586,7 +608,8 @@ kerberos5_is(ap, data, cnt)
char eerrbuf[329];
strcpy(eerrbuf, "telnetd: ");
- strcat(eerrbuf, errbuf);
+ eerrbuf[sizeof(eerrbuf) - 1] = '\0';
+ strncat(eerrbuf, errbuf, sizeof(eerrbuf) - 1 - strlen(eerrbuf));
Data(ap, KRB_REJECT, eerrbuf, -1);
}
if (auth_debug_mode)
@@ -706,7 +729,9 @@ kerberos5_status(ap, name, level)
krb5_kuserok(telnet_context, ticket->enc_part2->client,
UserNameRequested))
{
- strcpy(name, UserNameRequested);
+ /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+ strncpy(name, UserNameRequested, 255);
+ name[255] = '\0';
return(AUTH_VALID);
} else
return(AUTH_USER);
diff --git a/src/appl/telnet/libtelnet/setenv.c b/src/appl/telnet/libtelnet/setenv.c
index 70695a3..bc4f22d 100644
--- a/src/appl/telnet/libtelnet/setenv.c
+++ b/src/appl/telnet/libtelnet/setenv.c
@@ -52,6 +52,7 @@ static char *__findenv __P((const char *, int *));
* Set the value of the environmental variable "name" to be
* "value". If rewrite is set, replace any current value.
*/
+#ifndef HAVE_SETENV
setenv(name, value, rewrite)
register const char *name;
register const char *value;
@@ -102,11 +103,13 @@ setenv(name, value, rewrite)
for (*c++ = '='; *c++ = *value++;);
return (0);
}
+#endif
/*
* unsetenv(name) --
* Delete environmental variable "name".
*/
+#ifndef HAVE_UNSETENV
void
unsetenv(name)
const char *name;
@@ -120,11 +123,13 @@ unsetenv(name)
if (!(*p = *(p + 1)))
break;
}
+#endif
/*
* getenv --
* Returns ptr to value associated with name, if any, else NULL.
*/
+#ifndef HAVE_GETENV
char *
getenv(name)
const char *name;
@@ -133,6 +138,7 @@ getenv(name)
return (__findenv(name, &offset));
}
+#endif
/*
* __findenv --
diff --git a/src/appl/telnet/libtelnet/spx.c b/src/appl/telnet/libtelnet/spx.c
index f23490f..7285d0d 100644
--- a/src/appl/telnet/libtelnet/spx.c
+++ b/src/appl/telnet/libtelnet/spx.c
@@ -173,7 +173,8 @@ spx_init(ap, server)
str_data[3] = TELQUAL_REPLY;
gethostname(lhostname, sizeof(lhostname));
strcpy(targ_printable, "SERVICE:rcmd@");
- strcat(targ_printable, lhostname);
+ strncat(targ_printable, lhostname, sizeof(targ_printable) - 1 - 13);
+ targ_printable[sizeof(targ_printable) - 1] = '\0';
input_name_buffer.length = strlen(targ_printable);
input_name_buffer.value = targ_printable;
major_status = gss_import_name(&status,
@@ -216,7 +217,8 @@ spx_send(ap)
printf("[ Trying SPX ... ]\n");
strcpy(targ_printable, "SERVICE:rcmd@");
- strcat(targ_printable, RemoteHostName);
+ strncat(targ_printable, RemoteHostName, sizeof(targ_printable) - 1 - 13);
+ targ_printable[sizeof(targ_printable) - 1] = '\0';
input_name_buffer.length = strlen(targ_printable);
input_name_buffer.value = targ_printable;
@@ -324,7 +326,8 @@ spx_is(ap, data, cnt)
gethostname(lhostname, sizeof(lhostname));
strcpy(targ_printable, "SERVICE:rcmd@");
- strcat(targ_printable, lhostname);
+ strncat(targ_printable, lhostname, sizeof(targ_printable) - 1 - 13);
+ targ_printable[sizeof(targ_printable) - 1] = '\0';
input_name_buffer.length = strlen(targ_printable);
input_name_buffer.value = targ_printable;
@@ -479,7 +482,7 @@ spx_status(ap, name, level)
gss_buffer_desc fullname_buffer, acl_file_buffer;
gss_OID fullname_type;
- char acl_file[160], fullname[160];
+ char acl_file[MAXPATHLEN], fullname[160];
int major_status, status = 0;
struct passwd *pwd;
@@ -494,8 +497,9 @@ spx_status(ap, name, level)
return(AUTH_USER); /* not authenticated */
}
- strcpy(acl_file, pwd->pw_dir);
- strcat(acl_file, "/.sphinx");
+ acl_file[sizeof(acl_file) - 1] = '\0';
+ strncpy(acl_file, pwd->pw_dir, sizeof(acl_file) - 1);
+ strncat(acl_file, "/.sphinx", sizeof(acl_file) - 1 - strlen(acl_file));
acl_file_buffer.value = acl_file;
acl_file_buffer.length = strlen(acl_file);
@@ -511,7 +515,9 @@ spx_status(ap, name, level)
&acl_file_buffer);
if (major_status == GSS_S_COMPLETE) {
- strcpy(name, UserNameRequested);
+ /* the name buffer comes from telnetd/telnetd{-ktd}.c */
+ strncpy(name, UserNameRequested, 255);
+ name[255] = '\0';
return(AUTH_VALID);
} else {
return(AUTH_USER);
diff --git a/src/appl/telnet/telnet/ChangeLog b/src/appl/telnet/telnet/ChangeLog
index e3cfb63..fb7cc9394 100644
--- a/src/appl/telnet/telnet/ChangeLog
+++ b/src/appl/telnet/telnet/ChangeLog
@@ -1,3 +1,18 @@
+2000-05-11 Nalin Dahyabhai <nalin@redhat.com>
+
+ * commands.c (makeargv): Don't overflow buffer "saveline".
+ (tn): Don't overflow buffer "_hostname".
+ (cmdrc): Don't overflow buffer "m1save".
+ * externs.h: Include the size of "tline", so that we can check for
+ overflows elsewhere.
+ * main.c(main, tn370): Don't overflow buffer "tline".
+ * utilities.c (SetNetTrace): Don't overflow buffer "NetTraceFile".
+
+2000-04-28 Nalin Dahyabhai <nalin@redhat.com>
+
+ * commands.c (cmdrc): Don't overflow buffer "rcbuf".
+ * tn3270.c (settranscom): Don't overflow buffer "transcom".
+
2000-02-24 Ezra Peisach <epeisach@mit.edu>
* configure.in: Remove dependency on libdes425 when krb4 support
diff --git a/src/appl/telnet/telnet/commands.c b/src/appl/telnet/telnet/commands.c
index 2c80b0b..8ffba2e 100644
--- a/src/appl/telnet/telnet/commands.c
+++ b/src/appl/telnet/telnet/commands.c
@@ -138,7 +138,9 @@ makeargv()
margc = 0;
cp = line;
if (*cp == '!') { /* Special case shell escape */
- strcpy(saveline, line); /* save for shell command */
+ strncpy(saveline, line, sizeof(saveline) - 1);
+ /* save for shell command */
+ saveline[sizeof(saveline) - 1] = '\0';
*argp++ = "!"; /* No room in string to get this */
margc++;
cp++;
@@ -2450,7 +2452,8 @@ tn(argc, argv)
if (temp & 0xffffffff != INADDR_NONE) {
sin.sin_addr.s_addr = temp;
sin.sin_family = AF_INET;
- (void) strcpy(_hostname, hostp);
+ (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1);
+ _hostname[sizeof(_hostname) - 1] = '\0';
hostname = _hostname;
} else {
host = gethostbyname(hostp);
@@ -2855,16 +2858,18 @@ cmdrc(m1, m2)
if (skiprc)
return;
- strcpy(m1save, m1);
+ strncpy(m1save, m1, sizeof(m1save) - 1);
+ m1save[sizeof(m1save) - 1] = '\0';
m1 = m1save;
if (rcname == 0) {
rcname = getenv("HOME");
if (rcname)
- strcpy(rcbuf, rcname);
+ strncpy(rcbuf, rcname, sizeof(rcbuf) - 1);
else
rcbuf[0] = '\0';
- strcat(rcbuf, "/.telnetrc");
+ rcbuf[sizeof(rcbuf) - 1] = '\0';
+ strncat(rcbuf, "/.telnetrc", sizeof(rcbuf) - 1 - strlen(rcbuf));
rcname = rcbuf;
}
diff --git a/src/appl/telnet/telnet/externs.h b/src/appl/telnet/telnet/externs.h
index e993986..f35cded 100644
--- a/src/appl/telnet/telnet/externs.h
+++ b/src/appl/telnet/telnet/externs.h
@@ -486,7 +486,7 @@ extern char
*Ibackp, /* Oldest byte of 3270 data */
Ibuf[], /* 3270 buffer */
*Ifrontp, /* Where next 3270 byte goes */
- tline[],
+ tline[200],
*transcom; /* Transparent command */
extern int
diff --git a/src/appl/telnet/telnet/main.c b/src/appl/telnet/telnet/main.c
index da98ae6..7696857 100644
--- a/src/appl/telnet/telnet/main.c
+++ b/src/appl/telnet/telnet/main.c
@@ -274,7 +274,8 @@ main(argc, argv)
case 't':
#if defined(TN3270) && defined(unix)
transcom = tline;
- (void)strcpy(transcom, optarg);
+ (void)strncpy(transcom, optarg, sizeof(tline) - 1);
+ tline[sizeof(tline) - 1] = '\0';
#else
fprintf(stderr,
"%s: Warning: -t ignored, no TN3270 support.\n",
diff --git a/src/appl/telnet/telnet/tn3270.c b/src/appl/telnet/telnet/tn3270.c
index 77aedaf..c46ae7e 100644
--- a/src/appl/telnet/telnet/tn3270.c
+++ b/src/appl/telnet/telnet/tn3270.c
@@ -397,10 +397,11 @@ settranscom(argc, argv)
return 1;
}
transcom = tline;
- (void) strcpy(transcom, argv[1]);
+ (void) strncpy(transcom, argv[1], sizeof(tline) - 1);
+ tline[sizeof(tline) - 1] = '\0';
for (i = 2; i < argc; ++i) {
- (void) strcat(transcom, " ");
- (void) strcat(transcom, argv[i]);
+ (void) strncat(transcom, " ", sizeof(tline) - 1 - (transcom - tline));
+ (void) strncat(transcom, argv[i], sizeof(tline) - 1 - (transcom - tline));
}
return 1;
}
diff --git a/src/appl/telnet/telnet/utilities.c b/src/appl/telnet/telnet/utilities.c
index 19f503b..82ad841 100644
--- a/src/appl/telnet/telnet/utilities.c
+++ b/src/appl/telnet/telnet/utilities.c
@@ -113,13 +113,15 @@ SetNetTrace(file)
if (file && (strcmp(file, "-") != 0)) {
NetTrace = fopen(file, "w");
if (NetTrace) {
- strcpy((char *)NetTraceFile, file);
+ strncpy((char *)NetTraceFile, file, sizeof(NetTraceFile) - 1);
+ NetTraceFile[sizeof(NetTraceFile) - 1] = '\0';
return;
}
fprintf(stderr, "Cannot open %s.\n", file);
}
NetTrace = stdout;
- strcpy((char *)NetTraceFile, "(standard output)");
+ strncpy((char *)NetTraceFile, "(standard output)", sizeof(NetTraceFile) - 1);
+ NetTraceFile[sizeof(NetTraceFile) - 1] = '\0';
}
void
diff --git a/src/appl/telnet/telnetd/ChangeLog b/src/appl/telnet/telnetd/ChangeLog
index 040a9af..5ab914a 100644
--- a/src/appl/telnet/telnetd/ChangeLog
+++ b/src/appl/telnet/telnetd/ChangeLog
@@ -1,3 +1,70 @@
+2002-01-18 Tom Yu <tlyu@mit.edu>
+
+ * ext.h: Make stdarg prototypes unconditional, to avoid annoying
+ mostly-ANSI compilers that don't define __STDC__.
+
+2001-10-15 Ken Raeburn <raeburn@mit.edu>
+
+ * telnetd.c (valid_opts): Note that 'w' takes a parameter.
+
+2001-08-02 Tom Yu <tlyu@mit.edu>
+
+ * authenc.c (net_write): Rewrite in terms of netwrite().
+
+ * configure.in: Check for vsnprintf().
+
+ * ext.h: New prototypes for netprintf, netprintf_urg,
+ netprintf_noflush, netwrite, netputs.
+
+ * slc.c: Fix to use new NETOBUF-handling functions.
+
+ * state.c: Fix to use new NETOBUF-handling functions.
+
+ * telnetd.c: Fix to use new NETOBUF-handling functions.
+
+ * termstat.c: Fix to use new NETOBUF-handling functions.
+
+ * utility.c: General rework to be more paranoid about
+ bounds-checking of NETOBUF and NFRONTP. Abstract away
+ interactions with NETOBUF to eliminate explicit references to
+ NFRONTP in many places.
+ (netwrite): New function; copies a buffer to the
+ NETOBUF "ring buffer", checking bounds and calling netflush() if
+ needed.
+ (netputs): New function; calls netwrite() with a nul-terminated
+ string.
+ (netprintf, netprintf_ext): New function; wrap sprintf() with
+ bounds checking for use with NETOBUF.
+ (netprintf_urg): New function; like netprintf() except sets neturg
+ to point at last char written.
+ (netprintf_noflush): New function; like netprintf() except
+ silently fails if NETOBUF is full.
+ (ttloop, printoption, printsub, printdata): Fix to use new
+ NETOBUF-handling functions.
+
+2001-01-25 Tom Yu <tlyu@mit.edu>
+
+ * state.c (envvarok): Disallow LC_* and NLSPATH.
+
+2000-06-19 Tom Yu <tlyu@mit.edu>
+
+ * telnetd.c (doit): Change test for "no authentication" as per
+ Jeffrey Altman's patch.
+
+2000-05-11 Nalin Dahyabhai <nalin@redhat.com>
+
+ * sys_term.c (start_login, Solaris): forcefully terminate "termbuf"
+ in case the "TERM" environment variable isn't.
+ * telnet-ktd.c (getterminaltype): Don't overflow buffers "first" and
+ "netobuf".
+ (recv_ayt): Forcibly terminate buffer "netobuf".
+
+2000-03-20 Ken Raeburn <raeburn@mit.edu>
+ Jeffrey Altman <jaltman@watsun.cc.columbia.edu>
+
+ * state.c (telrcv): Fix off-by-one error dealing with full
+ buffer.
+
2000-02-24 Ezra Peisach <epeisach@mit.edu>
* configure.in: Remove dependency on libdes425 when krb4 support
diff --git a/src/appl/telnet/telnetd/authenc.c b/src/appl/telnet/telnetd/authenc.c
index 5736698..4488954 100644
--- a/src/appl/telnet/telnetd/authenc.c
+++ b/src/appl/telnet/telnetd/authenc.c
@@ -37,20 +37,17 @@
#include "telnetd.h"
#include <libtelnet/misc.h>
- int
+int
net_write(str, len)
unsigned char *str;
int len;
{
- if (nfrontp + len < netobuf + BUFSIZ) {
- memcpy((void *)nfrontp, (void *)str, len);
- nfrontp += len;
- return(len);
- }
- return(0);
+ if (len < 0)
+ return 0;
+ return netwrite(str, len);
}
- void
+void
net_encrypt()
{
#ifdef ENCRYPTION
@@ -87,7 +84,3 @@ telnet_gets(prompt, result, length, echo)
return((char *)0);
}
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
-
-
-
-
diff --git a/src/appl/telnet/telnetd/configure.in b/src/appl/telnet/telnetd/configure.in
index e11b270..2dc6099 100644
--- a/src/appl/telnet/telnetd/configure.in
+++ b/src/appl/telnet/telnetd/configure.in
@@ -23,7 +23,7 @@ fi
fi
AC_HEADER_TIME
AC_CHECK_HEADERS(string.h arpa/nameser.h utmp.h sys/time.h sys/tty.h sac.h sys/ptyvar.h sys/filio.h sys/stream.h sys/utsname.h)
-AC_CHECK_FUNCS(gettosbyname)
+AC_CHECK_FUNCS(gettosbyname vsnprintf)
dnl Make our operating system-specific security checks and definitions for
dnl login.
dnl
diff --git a/src/appl/telnet/telnetd/ext.h b/src/appl/telnet/telnetd/ext.h
index 2ff53e3..dc9fe5a 100644
--- a/src/appl/telnet/telnetd/ext.h
+++ b/src/appl/telnet/telnetd/ext.h
@@ -187,8 +187,13 @@ extern void
tty_setsofttab P((int)),
tty_tspeed P((int)),
willoption P((int)),
- wontoption P((int)),
- writenet P((unsigned char *, int));
+ wontoption P((int));
+
+extern void netprintf(const char *, ...);
+extern void netprintf_urg(const char *fmt, ...);
+extern void netprintf_noflush(const char *fmt, ...);
+extern int netwrite(const char *, size_t);
+extern void netputs(const char *);
#ifdef ENCRYPTION
extern char *nclearto;
diff --git a/src/appl/telnet/telnetd/slc.c b/src/appl/telnet/telnetd/slc.c
index 1c68b95..613674b 100644
--- a/src/appl/telnet/telnetd/slc.c
+++ b/src/appl/telnet/telnetd/slc.c
@@ -198,7 +198,7 @@ end_slc(bufp)
(void) sprintf((char *)slcptr, "%c%c", IAC, SE);
slcptr += 2;
len = slcptr - slcbuf;
- writenet(slcbuf, len);
+ netwrite(slcbuf, len);
netflush(); /* force it out immediately */
DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
}
diff --git a/src/appl/telnet/telnetd/state.c b/src/appl/telnet/telnetd/state.c
index 0f3b161..d783ed6 100644
--- a/src/appl/telnet/telnetd/state.c
+++ b/src/appl/telnet/telnetd/state.c
@@ -86,7 +86,7 @@ static void sb_auth_complete()
if (!auth_negotiated) {
static char *error =
"An environment option was sent before authentication negotiation completed.\r\nThis may create a security hazard. Connection dropped.\r\n";
- writenet(error, strlen(error));
+ netputs(error);
netflush();
exit(1);
}
@@ -102,7 +102,7 @@ telrcv()
#endif
while (ncc > 0) {
- if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
+ if ((&ptyobuf[BUFSIZ] - pfrontp) < 1)
break;
c = *netip++ & 0377, ncc--;
#ifdef ENCRYPTION
@@ -209,9 +209,7 @@ gotiac: switch (c) {
}
netclear(); /* clear buffer back */
- *nfrontp++ = IAC;
- *nfrontp++ = DM;
- neturg = nfrontp-1; /* off by one XXX */
+ netprintf_urg("%c%c", IAC, DM);
DIAG(TD_OPTIONS,
printoption("td: send IAC", DM));
break;
@@ -381,9 +379,12 @@ gotiac: switch (c) {
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;
+ for (cp = xbuf2; oc > 0; --oc) {
+ if (*cp == IAC)
+ netprintf("%c%c", *cp++, IAC);
+ else
+ netprintf("%c", *cp++);
+ }
}
#endif /* defined(CRAY2) && defined(UNICOS5) */
} /* end of telrcv */
@@ -463,8 +464,7 @@ send_do(option, init)
set_his_want_state_will(option);
do_dont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)doopt, option);
- nfrontp += sizeof (dont) - 2;
+ netprintf((char *)doopt, option);
DIAG(TD_OPTIONS, printoption("td: send do", option));
}
@@ -683,8 +683,7 @@ send_dont(option, init)
set_his_want_state_wont(option);
do_dont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)dont, option);
- nfrontp += sizeof (doopt) - 2;
+ netprintf((char *)dont, option);
DIAG(TD_OPTIONS, printoption("td: send dont", option));
}
@@ -833,8 +832,7 @@ send_will(option, init)
set_my_want_state_will(option);
will_wont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)will, option);
- nfrontp += sizeof (doopt) - 2;
+ netprintf((char *)will, option);
DIAG(TD_OPTIONS, printoption("td: send will", option));
}
@@ -993,8 +991,7 @@ send_wont(option, init)
set_my_want_state_wont(option);
will_wont_resp[option]++;
}
- (void) sprintf(nfrontp, (char *)wont, option);
- nfrontp += sizeof (wont) - 2;
+ netprintf((char *)wont, option);
DIAG(TD_OPTIONS, printoption("td: send wont", option));
}
@@ -1393,10 +1390,8 @@ suboption()
env_ovar_wrong:
env_ovar = OLD_ENV_VALUE;
env_ovalue = OLD_ENV_VAR;
- DIAG(TD_OPTIONS, {sprintf(nfrontp,
- "ENVIRON VALUE and VAR are reversed!\r\n");
- nfrontp += strlen(nfrontp);});
-
+ DIAG(TD_OPTIONS,
+ netputs("ENVIRON VALUE and VAR are reversed!\r\n"));
}
}
SB_RESTORE();
@@ -1633,7 +1628,7 @@ send_status()
ADD(IAC);
ADD(SE);
- writenet(statusbuf, ncp - statusbuf);
+ netwrite(statusbuf, ncp - statusbuf);
netflush(); /* Send it on its way */
DIAG(TD_OPTIONS,
@@ -1663,6 +1658,8 @@ static int envvarok(varp)
strcmp(varp, "KRB_REALMS") && /* cns v4 */
strcmp(varp, "LIBPATH") && /* AIX */
strcmp(varp, "RESOLV_HOST_CONF") && /* linux */
+ strcmp(varp, "NLSPATH") && /* locale stuff */
+ strncmp(varp, "LC_", strlen("LC_")) && /* locale stuff */
strcmp(varp, "IFS")) {
return 1;
} else {
diff --git a/src/appl/telnet/telnetd/sys_term.c b/src/appl/telnet/telnetd/sys_term.c
index ee8d53d..b79209d 100644
--- a/src/appl/telnet/telnetd/sys_term.c
+++ b/src/appl/telnet/telnetd/sys_term.c
@@ -1257,6 +1257,7 @@ start_login(host, autologin, name)
} else {
strcpy(termbuf, "TERM=");
strncat(termbuf, term, sizeof(termbuf) - 6);
+ termbuf[sizeof(termbuf) - 1] = '\0';
term = termbuf;
}
argv = addarg(argv, term);
diff --git a/src/appl/telnet/telnetd/telnetd-ktd.c b/src/appl/telnet/telnetd/telnetd-ktd.c
index 9ec608f..5936e3b 100644
--- a/src/appl/telnet/telnetd/telnetd-ktd.c
+++ b/src/appl/telnet/telnetd/telnetd-ktd.c
@@ -360,7 +360,7 @@ main(argc, argv)
}
(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on));
- if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("bind");
exit(1);
}
@@ -368,7 +368,7 @@ main(argc, argv)
perror("listen");
exit(1);
}
- foo = sizeof sin;
+ foo = sizeof(sin);
ns = accept(s, (struct sockaddr *)&sin, &foo);
if (ns < 0) {
perror("accept");
@@ -548,25 +548,33 @@ getterminaltype(name)
if (his_state_is_will(TELOPT_TSPEED)) {
static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
- memcpy(nfrontp, sbbuf, sizeof sbbuf);
- nfrontp += sizeof sbbuf;
+ if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+ memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+ nfrontp += sizeof(sbbuf);
+ }
}
if (his_state_is_will(TELOPT_XDISPLOC)) {
static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
- memcpy(nfrontp, sbbuf, sizeof sbbuf);
- nfrontp += sizeof sbbuf;
+ if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+ memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+ nfrontp += sizeof(sbbuf);
+ }
}
if (his_state_is_will(TELOPT_ENVIRON)) {
static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE };
- memcpy(nfrontp, sbbuf, sizeof sbbuf);
- nfrontp += sizeof sbbuf;
+ if(nfrontp - netobuf + sizeof(sbbuf) < sizeof(netobuf)) {
+ memcpy(nfrontp, sbbuf, sizeof(sbbuf));
+ nfrontp += sizeof(sbbuf);
+ }
}
if (his_state_is_will(TELOPT_TTYPE)) {
- memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
- nfrontp += sizeof ttytype_sbbuf;
+ if(nfrontp - netobuf + sizeof(ttytype_sbbuf) < sizeof(netobuf)) {
+ memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+ nfrontp += sizeof(ttytype_sbbuf);
+ }
}
if (his_state_is_will(TELOPT_TSPEED)) {
while (sequenceIs(tspeedsubopt, baseline))
@@ -591,12 +599,14 @@ getterminaltype(name)
* we have to just go with what we (might) have already gotten.
*/
if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
- (void) strncpy(first, terminaltype, sizeof(first));
+ (void) strncpy(first, terminaltype, sizeof(first) - 1);
+ first[sizeof(first) - 1] = '\0';
for(;;) {
/*
* Save the unknown name, and request the next name.
*/
- (void) strncpy(last, terminaltype, sizeof(last));
+ (void) strncpy(last, terminaltype, sizeof(last) - 1);
+ last[sizeof(last) - 1] = '\0';
_gettermname();
if (terminaltypeok(terminaltype))
break;
@@ -615,7 +625,8 @@ getterminaltype(name)
*/
_gettermname();
if (strncmp(first, terminaltype, sizeof(first)) != 0)
- (void) strncpy(terminaltype, first, sizeof(first));
+ (void) strncpy(terminaltype, first, sizeof(terminaltype) - 1);
+ terminaltype[sizeof(terminaltype) - 1] = '\0';
break;
}
}
@@ -635,8 +646,8 @@ _gettermname()
if (his_state_is_wont(TELOPT_TTYPE))
return;
settimer(baseline);
- memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
- nfrontp += sizeof ttytype_sbbuf;
+ memcpy(nfrontp, ttytype_sbbuf, sizeof(ttytype_sbbuf));
+ nfrontp += sizeof(ttytype_sbbuf);
while (sequenceIs(ttypesubopt, baseline))
ttloop();
}
@@ -922,7 +933,7 @@ telnet(f, p, host)
#if defined(SO_OOBINLINE)
(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
- (char *)&on, sizeof on);
+ (char *)&on, sizeof(on));
#endif /* defined(SO_OOBINLINE) */
#ifdef SIGTSTP
@@ -989,8 +1000,10 @@ telnet(f, p, host)
HE = getstr("he", &cp);
HN = getstr("hn", &cp);
IM = getstr("im", &cp);
- if (HN && *HN)
- (void) strcpy(host_name, HN);
+ if (HN && *HN) {
+ (void) strncpy(host_name, HN, sizeof(host_name) - 1);
+ host_name[sizeof(host_name) - 1] = '\0';
+ }
if (IM == 0)
IM = "";
} else {
@@ -1426,8 +1439,10 @@ recv_ayt()
return;
}
#endif
- (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
+ (void) strncpy(nfrontp, "\r\n[Yes]\r\n",
+ sizeof(netobuf) - 1 - (nfrontp - netobuf));
nfrontp += 9;
+ *nfrontp = '\0';
}
void
diff --git a/src/appl/telnet/telnetd/telnetd.c b/src/appl/telnet/telnetd/telnetd.c
index 7267469..5588d1a 100644
--- a/src/appl/telnet/telnetd/telnetd.c
+++ b/src/appl/telnet/telnetd/telnetd.c
@@ -153,7 +153,7 @@ extern void usage P((void));
*/
char valid_opts[] = {
'd', ':', 'h', 'k', 'L', ':', 'n', 'S', ':', 'U',
- 'w',
+ 'w', ':',
#ifdef AUTHENTICATION
'a', ':', 'X', ':',
#endif
@@ -522,7 +522,7 @@ main(argc, argv)
}
(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on));
- if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("bind");
exit(1);
}
@@ -530,7 +530,7 @@ main(argc, argv)
perror("listen");
exit(1);
}
- foo = sizeof sin;
+ foo = sizeof(sin);
ns = accept(s, (struct sockaddr *)&sin, &foo);
if (ns < 0) {
perror("accept");
@@ -693,7 +693,7 @@ static void encrypt_failure()
char *error_message =
"Encryption was not successfully negotiated. Goodbye.\r\n\r\n";
- writenet(error_message, strlen(error_message));
+ netputs(error_message);
netflush();
exit(1);
}
@@ -780,36 +780,26 @@ getterminaltype(name)
if (his_state_is_will(TELOPT_TSPEED)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
-
- memcpy(nfrontp, sb, sizeof sb);
- nfrontp += sizeof sb;
+ netwrite(sb, sizeof(sb));
}
if (his_state_is_will(TELOPT_XDISPLOC)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
-
- memcpy(nfrontp, sb, sizeof sb);
- nfrontp += sizeof sb;
+ netwrite(sb, sizeof(sb));
}
if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
-
- memcpy(nfrontp, sb, sizeof sb);
- nfrontp += sizeof sb;
+ netwrite(sb, sizeof(sb));
}
else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
static unsigned char sb[] =
{ IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
-
- memcpy(nfrontp, sb, sizeof sb);
- nfrontp += sizeof sb;
+ netwrite(sb, sizeof(sb));
}
- if (his_state_is_will(TELOPT_TTYPE)) {
+ if (his_state_is_will(TELOPT_TTYPE))
+ netwrite(ttytype_sbbuf, sizeof(ttytype_sbbuf));
- memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
- nfrontp += sizeof ttytype_sbbuf;
- }
if (his_state_is_will(TELOPT_TSPEED)) {
while (sequenceIs(tspeedsubopt, baseline))
ttloop();
@@ -886,8 +876,7 @@ _gettermname()
if (his_state_is_wont(TELOPT_TTYPE))
return;
settimer(baseline);
- memcpy(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf);
- nfrontp += sizeof ttytype_sbbuf;
+ netwrite(ttytype_sbbuf, sizeof(ttytype_sbbuf));
while (sequenceIs(ttypesubopt, baseline))
ttloop();
}
@@ -1009,7 +998,7 @@ pty_init();
setenv("TERM", *terminaltype ? terminaltype : "network", 1);
#if defined (AUTHENTICATION)
- if (user_name[0] == '\0') {
+ if (level < 0 && auth_level > 0) {
fatal (net, "No authentication provided");
exit (-1);
}
@@ -1159,9 +1148,7 @@ telnet(f, p, host)
* mode, which we do not want.
*/
if (his_want_state_is_will(TELOPT_ECHO)) {
- DIAG(TD_OPTIONS,
- {sprintf(nfrontp, "td: simulating recv\r\n");
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_OPTIONS, netputs("td: simulating recv\r\n"));
willoption(TELOPT_ECHO);
}
@@ -1205,7 +1192,7 @@ telnet(f, p, host)
#if defined(SO_OOBINLINE)
(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
- (char *)&on, sizeof on);
+ (char *)&on, sizeof(on));
#endif /* defined(SO_OOBINLINE) */
#ifdef SIGTSTP
@@ -1266,7 +1253,8 @@ telnet(f, p, host)
HN = getstr("hn", &cp);
IM = getstr("im", &cp);
if (HN && *HN)
- (void) strcpy(host_name, HN);
+ (void) strncpy(host_name, HN, sizeof(host_name) - 1);
+ host_name[sizeof(host_name) - 1] = '\0';
if (IM == 0)
IM = "";
} else {
@@ -1289,9 +1277,7 @@ telnet(f, p, host)
localstat();
#endif /* LINEMODE */
- DIAG(TD_REPORT,
- {sprintf(nfrontp, "td: Entering processing loop\r\n");
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_REPORT, netputs("td: Entering processing loop\r\n"));
#ifdef convex
startslave(host);
@@ -1416,8 +1402,7 @@ telnet(f, p, host)
netip = netibuf;
}
DIAG((TD_REPORT | TD_NETDATA),
- {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);
- nfrontp += strlen(nfrontp);});
+ netprintf("td: netread %d chars\r\n", ncc));
DIAG(TD_NETDATA, printdata("nd", netip, ncc));
}
@@ -1464,9 +1449,7 @@ telnet(f, p, host)
* royally if we send them urgent
* mode data.
*/
- *nfrontp++ = IAC;
- *nfrontp++ = DM;
- neturg = nfrontp-1; /* off by one XXX */
+ netprintf_urg("%c%c", IAC, DM);
#endif
}
if (his_state_is_will(TELOPT_LFLOW) &&
@@ -1476,13 +1459,11 @@ telnet(f, p, host)
ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
if (newflow != flowmode) {
flowmode = newflow;
- (void) sprintf(nfrontp,
- "%c%c%c%c%c%c",
+ netprintf("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
flowmode ? LFLOW_ON
: LFLOW_OFF,
IAC, SE);
- nfrontp += 6;
}
}
pcc--;
@@ -1505,19 +1486,19 @@ telnet(f, p, host)
break;
c = *ptyip++ & 0377, pcc--;
if (c == IAC)
- *nfrontp++ = c;
+ netprintf("%c", c);
#if defined(CRAY2) && defined(UNICOS5)
else if (c == '\n' &&
my_state_is_wont(TELOPT_BINARY) && newmap)
- *nfrontp++ = '\r';
+ netputs("\r");
#endif /* defined(CRAY2) && defined(UNICOS5) */
- *nfrontp++ = c;
+ netprintf("%c", c);
if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
- *nfrontp++ = *ptyip++ & 0377;
+ netprintf("%c", *ptyip++ & 0377);
pcc--;
} else
- *nfrontp++ = '\0';
+ netprintf("%c", '\0');
}
}
#if defined(CRAY2) && defined(UNICOS5)
@@ -1679,7 +1660,7 @@ sendsusp()
* When we get an AYT, if ^T is enabled, use that. Otherwise,
* just send back "[Yes]".
*/
- void
+void
recv_ayt()
{
#if defined(SIGINFO) && defined(TCSIG)
@@ -1688,8 +1669,7 @@ recv_ayt()
return;
}
#endif
- (void) strcpy(nfrontp, "\r\n[Yes]\r\n");
- nfrontp += 9;
+ netputs("\r\n[Yes]\r\n");
}
void
diff --git a/src/appl/telnet/telnetd/termstat.c b/src/appl/telnet/telnetd/termstat.c
index 824a1a6..531e167 100644
--- a/src/appl/telnet/telnetd/termstat.c
+++ b/src/appl/telnet/telnetd/termstat.c
@@ -283,10 +283,9 @@ localstat()
# endif /* KLUDGELINEMODE */
send_do(TELOPT_LINEMODE, 1);
/* send along edit modes */
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
+ netprintf("%c%c%c%c%c%c%c", IAC, SB,
TELOPT_LINEMODE, LM_MODE, useeditmode,
IAC, SE);
- nfrontp += 7;
editmode = useeditmode;
# ifdef KLUDGELINEMODE
}
@@ -312,10 +311,9 @@ localstat()
/*
* Send along appropriate edit mode mask.
*/
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
+ (void) netprintf("%c%c%c%c%c%c%c", IAC, SB,
TELOPT_LINEMODE, LM_MODE, useeditmode,
IAC, SE);
- nfrontp += 7;
editmode = useeditmode;
}
@@ -359,20 +357,18 @@ flowstat()
if (his_state_is_will(TELOPT_LFLOW)) {
if (tty_flowmode() != flowmode) {
flowmode = tty_flowmode();
- (void) sprintf(nfrontp, "%c%c%c%c%c%c",
+ netprintf("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
flowmode ? LFLOW_ON : LFLOW_OFF,
IAC, SE);
- nfrontp += 6;
}
if (tty_restartany() != restartany) {
restartany = tty_restartany();
- (void) sprintf(nfrontp, "%c%c%c%c%c%c",
+ netprintf("%c%c%c%c%c%c",
IAC, SB, TELOPT_LFLOW,
restartany ? LFLOW_RESTART_ANY
: LFLOW_RESTART_XON,
IAC, SE);
- nfrontp += 6;
}
}
}
@@ -445,10 +441,9 @@ clientstat(code, parm1, parm2)
useeditmode |= MODE_SOFT_TAB;
if (tty_islitecho())
useeditmode |= MODE_LIT_ECHO;
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
+ netprintf("%c%c%c%c%c%c%c", IAC,
SB, TELOPT_LINEMODE, LM_MODE,
- useeditmode, IAC, SE);
- nfrontp += 7;
+ useeditmode, IAC, SE);
editmode = useeditmode;
}
@@ -504,11 +499,10 @@ clientstat(code, parm1, parm2)
set_termbuf();
if (!ack) {
- (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
+ netprintf("%c%c%c%c%c%c%c", IAC,
SB, TELOPT_LINEMODE, LM_MODE,
useeditmode|MODE_ACK,
IAC, SE);
- nfrontp += 7;
}
editmode = useeditmode;
diff --git a/src/appl/telnet/telnetd/utility.c b/src/appl/telnet/telnetd/utility.c
index 408c6f4..93a932d 100644
--- a/src/appl/telnet/telnetd/utility.c
+++ b/src/appl/telnet/telnetd/utility.c
@@ -33,6 +33,7 @@
/* based on @(#)utility.c 8.1 (Berkeley) 6/4/93 */
+#include <stdarg.h>
#define PRINTOPTIONS
#include "telnetd.h"
@@ -58,8 +59,7 @@ ttloop()
{
void netflush();
- DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n");
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_REPORT, netputs("td: ttloop\r\n"));
if (nfrontp-nbackp) {
netflush();
}
@@ -74,8 +74,7 @@ read_again:
syslog(LOG_INFO, "ttloop: peer died: %m");
exit(1);
}
- DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc);
- nfrontp += strlen(nfrontp);});
+ DIAG(TD_REPORT, netprintf("td: ttloop read %d chars\r\n", ncc));
netip = netibuf;
telrcv(); /* state machine */
if (ncc > 0) {
@@ -118,8 +117,7 @@ ptyflush()
if ((n = pfrontp - pbackp) > 0) {
DIAG((TD_REPORT | TD_PTYDATA),
- { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n);
- nfrontp += strlen(nfrontp); });
+ netprintf("td: ptyflush %d chars\r\n", n));
DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
n = write(pty, pbackp, n);
}
@@ -244,18 +242,15 @@ netclear()
* Send as much data as possible to the network,
* handling requests for urgent data.
*/
- void
+void
netflush()
{
int n;
extern int not42;
if ((n = nfrontp - nbackp) > 0) {
- DIAG(TD_REPORT,
- { sprintf(nfrontp, "td: netflush %d chars\r\n", n);
- n += strlen(nfrontp); /* get count first */
- nfrontp += strlen(nfrontp); /* then move pointer */
- });
+ DIAG(TD_REPORT, {netprintf_noflush("td: netflush %d chars\r\n", n);
+ n = nfrontp - nbackp;});
#ifdef ENCRYPTION
if (encrypt_output) {
char *s = nclearto ? nclearto : nbackp;
@@ -312,33 +307,131 @@ netflush()
return;
} /* end of netflush */
+/*
+ * L8_256(x) = log8(256**x), rounded up, including sign (for decimal
+ * strings too). log8(256) = 8/3, but we use integer math to round
+ * up.
+ */
+#define L8_256(x) (((x * 8 + 2) / 3) + 1)
/*
- * writenet
+ * netprintf
*
- * Just a handy little function to write a bit of raw data to the net.
- * It will force a transmit of the buffer if necessary
+ * Do the equivalent of printf() to the NETOBUF "ring buffer",
+ * possibly calling netflush() if needed.
*
- * arguments
- * ptr - A pointer to a character string to write
- * len - How many bytes to write
+ * Thou shalt not call this with a "%s" format; use netputs instead.
+ * We also don't deal with floating point widths in here.
*/
- void
-writenet(ptr, len)
- register unsigned char *ptr;
- register int len;
+void
+netprintf_ext(int noflush, int seturg, const char *fmt, va_list args)
{
- /* flush buffer if no room for new data) */
- if ((&netobuf[BUFSIZ] - nfrontp) < len) {
- /* if this fails, don't worry, buffer is a little big */
- netflush();
+ size_t remain;
+ size_t maxoutlen;
+ char buf[BUFSIZ];
+ const char *cp;
+ int len;
+
+ buf[0] = '\0'; /* nul-terminate */
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ for (maxoutlen = 0, cp = fmt; *cp; cp++) {
+ if (*cp == '%')
+ /* Ok so this is slightly overkill... */
+ maxoutlen += L8_256(sizeof(long));
+ else
+ maxoutlen++;
}
+ if (maxoutlen >= sizeof(buf))
+ return; /* highly unlikely */
- memcpy(nfrontp, ptr, len);
+#ifdef HAVE_VSNPRINTF
+ len = vsnprintf(buf, sizeof(buf), fmt, args);
+#else
+ len = vsprintf(buf, fmt, args); /* XXX need to fix for SunOS? */
+#endif
+
+ /*
+ * The return value from sprintf()-like functions may be the
+ * number of characters that *would* have been output, not the
+ * number actually output.
+ */
+ if (len <= 0 || len > sizeof(buf))
+ return;
+ if (remain < len && !noflush) {
+ netflush();
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ }
+ if (remain < len)
+ return; /* still not enough space? */
+ memcpy(nfrontp, buf, (size_t)len);
nfrontp += len;
+ if (seturg)
+ neturg = nfrontp - 1;
+}
+
+void
+netprintf(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ netprintf_ext(0, 0, fmt, args);
+ va_end(args);
+}
+
+void
+netprintf_urg(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ netprintf_ext(0, 1, fmt, args);
+ va_end(args);
+}
+
+void
+netprintf_noflush(const char *fmt, ...)
+{
+ va_list args;
-} /* end of writenet */
+ va_start(args, fmt);
+ netprintf_ext(1, 0, fmt, args);
+ va_end(args);
+}
+
+/*
+ * netwrite
+ *
+ * Copy BUF into the NETOBUF "ring buffer", possibly calling
+ * netflush() if needed.
+ */
+int
+netwrite(const char *buf, size_t len)
+{
+ size_t remain;
+
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ if (remain < len) {
+ netflush();
+ remain = sizeof(netobuf) - (nfrontp - netobuf);
+ }
+ if (remain < len)
+ return 0;
+ memcpy(nfrontp, buf, len);
+ nfrontp += len;
+ return len;
+}
+/*
+ * netputs
+ *
+ * Write S to the NETOBUF "ring buffer". Does not write a '\n'.
+ */
+void
+netputs(const char *s)
+{
+ netwrite(s, strlen(s));
+}
/*
* miscellaneous functions doing a variety of little jobs follow ...
@@ -522,22 +615,26 @@ putf(cp, where)
/*
* Print telnet options and commands in plain text, if possible.
*/
- void
+void
printoption(fmt, option)
register char *fmt;
register int option;
{
- if (TELOPT_OK(option))
- sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option));
- else if (TELCMD_OK(option))
- sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option));
- else
- sprintf(nfrontp, "%s %d\r\n", fmt, option);
- nfrontp += strlen(nfrontp);
+ netputs(fmt);
+ netputs(" ");
+ if (TELOPT_OK(option)) {
+ netputs(TELOPT(option));
+ netputs("\r\n");
+ } else if (TELCMD_OK(option)) {
+ netputs(TELCMD(option));
+ netputs("\r\n");
+ } else {
+ netprintf("%d\r\n", option);
+ }
return;
}
- void
+void
printsub(direction, pointer, length)
char direction; /* '<' or '>' */
unsigned char *pointer; /* where suboption data sits */
@@ -550,9 +647,9 @@ printsub(direction, pointer, length)
return;
if (direction) {
- sprintf(nfrontp, "td: %s suboption ",
- direction == '<' ? "recv" : "send");
- nfrontp += strlen(nfrontp);
+ netputs("td: ");
+ netputs(direction == '<' ? "recv" : "send");
+ netputs(" suboption ");
if (length >= 3) {
register int j;
@@ -560,261 +657,223 @@ printsub(direction, pointer, length)
j = pointer[length-1];
if (i != IAC || j != SE) {
- sprintf(nfrontp, "(terminated by ");
- nfrontp += strlen(nfrontp);
+ netputs("(terminated by ");
if (TELOPT_OK(i))
- sprintf(nfrontp, "%s ", TELOPT(i));
+ netputs(TELOPT(i));
else if (TELCMD_OK(i))
- sprintf(nfrontp, "%s ", TELCMD(i));
+ netputs(TELCMD(i));
else
- sprintf(nfrontp, "%d ", i);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", i);
+ netputs(" ");
if (TELOPT_OK(j))
- sprintf(nfrontp, "%s", TELOPT(j));
+ netputs(TELOPT(j));
else if (TELCMD_OK(j))
- sprintf(nfrontp, "%s", TELCMD(j));
+ netputs(TELCMD(j));
else
- sprintf(nfrontp, "%d", j);
- nfrontp += strlen(nfrontp);
- sprintf(nfrontp, ", not IAC SE!) ");
- nfrontp += strlen(nfrontp);
+ netprintf("%d", j);
+ netputs(", not IAC SE!) ");
}
}
length -= 2;
}
if (length < 1) {
- sprintf(nfrontp, "(Empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(Empty suboption??\?)");
return;
}
switch (pointer[0]) {
case TELOPT_TTYPE:
- sprintf(nfrontp, "TERMINAL-TYPE ");
- nfrontp += strlen(nfrontp);
+ netputs("TERMINAL-TYPE ");
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ netputs("IS \"");
+ netwrite((char *)pointer + 2, (size_t)(length - 2));
+ netputs("\"");
break;
case TELQUAL_SEND:
- sprintf(nfrontp, "SEND");
+ netputs("SEND");
break;
default:
- sprintf(nfrontp,
- "- unknown qualifier %d (0x%x).",
- pointer[1], pointer[1]);
+ netprintf("- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
}
- nfrontp += strlen(nfrontp);
break;
case TELOPT_TSPEED:
- sprintf(nfrontp, "TERMINAL-SPEED");
- nfrontp += strlen(nfrontp);
+ netputs("TERMINAL-SPEED ");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(empty suboption??\?)");
break;
}
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2);
- nfrontp += strlen(nfrontp);
+ netputs("IS ");
+ netwrite((char *)pointer + 2, (size_t)(length - 2));
break;
default:
if (pointer[1] == 1)
- sprintf(nfrontp, " SEND");
+ netputs("SEND");
else
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
}
break;
case TELOPT_LFLOW:
- sprintf(nfrontp, "TOGGLE-FLOW-CONTROL");
- nfrontp += strlen(nfrontp);
+ netputs("TOGGLE-FLOW-CONTROL ");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(empty suboption??\?)");
break;
}
switch (pointer[1]) {
case LFLOW_OFF:
- sprintf(nfrontp, " OFF"); break;
+ netputs("OFF"); break;
case LFLOW_ON:
- sprintf(nfrontp, " ON"); break;
+ netputs("ON"); break;
case LFLOW_RESTART_ANY:
- sprintf(nfrontp, " RESTART-ANY"); break;
+ netputs("RESTART-ANY"); break;
case LFLOW_RESTART_XON:
- sprintf(nfrontp, " RESTART-XON"); break;
+ netputs("RESTART-XON"); break;
default:
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- }
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d (unknown)", pointer[1]);
}
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case TELOPT_NAWS:
- sprintf(nfrontp, "NAWS");
- nfrontp += strlen(nfrontp);
+ netputs("NAWS");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (empty suboption??\?)");
break;
}
if (length == 2) {
- sprintf(nfrontp, " ?%d?", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netprintf(" ?%d?", pointer[1]);
break;
}
- sprintf(nfrontp, " %d %d (%d)",
+ netprintf(" %d %d (%d)",
pointer[1], pointer[2],
(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
- nfrontp += strlen(nfrontp);
if (length == 4) {
- sprintf(nfrontp, " ?%d?", pointer[3]);
- nfrontp += strlen(nfrontp);
+ netprintf(" ?%d?", pointer[3]);
break;
}
- sprintf(nfrontp, " %d %d (%d)",
+ netprintf(" %d %d (%d)",
pointer[3], pointer[4],
(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
- nfrontp += strlen(nfrontp);
- for (i = 5; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (i = 5; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case TELOPT_LINEMODE:
- sprintf(nfrontp, "LINEMODE ");
- nfrontp += strlen(nfrontp);
+ netputs("LINEMODE ");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(empty suboption??\?)");
break;
}
switch (pointer[1]) {
case WILL:
- sprintf(nfrontp, "WILL ");
+ netputs("WILL ");
goto common;
case WONT:
- sprintf(nfrontp, "WONT ");
+ netputs("WONT ");
goto common;
case DO:
- sprintf(nfrontp, "DO ");
+ netputs("DO ");
goto common;
case DONT:
- sprintf(nfrontp, "DONT ");
+ netputs("DONT ");
common:
- nfrontp += strlen(nfrontp);
if (length < 3) {
- sprintf(nfrontp, "(no option??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(no option??\?)");
break;
}
switch (pointer[2]) {
case LM_FORWARDMASK:
- sprintf(nfrontp, "Forward Mask");
- nfrontp += strlen(nfrontp);
- for (i = 3; i < length; i++) {
- sprintf(nfrontp, " %x", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netputs("Forward Mask");
+ for (i = 3; i < length; i++)
+ netprintf(" %x", pointer[i]);
break;
default:
- sprintf(nfrontp, "%d (unknown)", pointer[2]);
- nfrontp += strlen(nfrontp);
- for (i = 3; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d (unknown)", pointer[2]);
+ for (i = 3; i < length; i++)
+ netprintf(" %d", pointer[i]);
break;
}
break;
case LM_SLC:
- sprintf(nfrontp, "SLC");
- nfrontp += strlen(nfrontp);
+ netputs("SLC");
for (i = 2; i < length - 2; i += 3) {
- if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
- sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
- else
- sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]);
- nfrontp += strlen(nfrontp);
+ if (SLC_NAME_OK(pointer[i+SLC_FUNC])) {
+ netputs(" ");
+ netputs(SLC_NAME(pointer[i+SLC_FUNC]));
+ } else
+ netprintf(" %d", pointer[i+SLC_FUNC]);
switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
case SLC_NOSUPPORT:
- sprintf(nfrontp, " NOSUPPORT"); break;
+ netputs(" NOSUPPORT"); break;
case SLC_CANTCHANGE:
- sprintf(nfrontp, " CANTCHANGE"); break;
+ netputs(" CANTCHANGE"); break;
case SLC_VARIABLE:
- sprintf(nfrontp, " VARIABLE"); break;
+ netputs(" VARIABLE"); break;
case SLC_DEFAULT:
- sprintf(nfrontp, " DEFAULT"); break;
+ netputs(" DEFAULT"); break;
}
- nfrontp += strlen(nfrontp);
- sprintf(nfrontp, "%s%s%s",
- pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
- pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
- pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
- nfrontp += strlen(nfrontp);
+ netputs(pointer[i+SLC_FLAGS]&SLC_ACK
+ ? "|ACK" : "");
+ netputs(pointer[i+SLC_FLAGS]&SLC_FLUSHIN
+ ? "|FLUSHIN" : "");
+ netputs(pointer[i+SLC_FLAGS]&SLC_FLUSHOUT
+ ? "|FLUSHOUT" : "");
if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
SLC_FLUSHOUT| SLC_LEVELBITS)) {
- sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]);
- nfrontp += strlen(nfrontp);
+ netprintf("(0x%x)", pointer[i+SLC_FLAGS]);
}
- sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d;", pointer[i+SLC_VALUE]);
if ((pointer[i+SLC_VALUE] == IAC) &&
(pointer[i+SLC_VALUE+1] == IAC))
i++;
}
- for (; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case LM_MODE:
- sprintf(nfrontp, "MODE ");
- nfrontp += strlen(nfrontp);
+ netputs("MODE ");
if (length < 3) {
- sprintf(nfrontp, "(no mode??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(no mode??\?)");
break;
}
{
- char tbuf[32];
- sprintf(tbuf, "%s%s%s%s%s",
- pointer[2]&MODE_EDIT ? "|EDIT" : "",
- pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
- pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
- pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
- pointer[2]&MODE_ACK ? "|ACK" : "");
- sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0");
- nfrontp += strlen(nfrontp);
- }
- if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) {
- sprintf(nfrontp, " (0x%x)", pointer[2]);
- nfrontp += strlen(nfrontp);
- }
- for (i = 3; i < length; i++) {
- sprintf(nfrontp, " ?0x%x?", pointer[i]);
- nfrontp += strlen(nfrontp);
+ int wrotemode = 0;
+
+#define NETPUTS_MODE(x) \
+do { \
+ if (pointer[2] & (MODE_##x)) { \
+ if (wrotemode) netputs("|"); \
+ netputs(#x); \
+ wrotemode++; \
+ } \
+} while (0)
+ NETPUTS_MODE(EDIT);
+ NETPUTS_MODE(TRAPSIG);
+ NETPUTS_MODE(SOFT_TAB);
+ NETPUTS_MODE(LIT_ECHO);
+ NETPUTS_MODE(ACK);
+#undef NETPUTS_MODE
+ if (!wrotemode)
+ netputs("0");
}
+ if (pointer[2] & ~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
+ netprintf(" (0x%x)", pointer[2]);
+ for (i = 3; i < length; i++)
+ netprintf(" ?0x%x?", pointer[i]);
break;
default:
- sprintf(nfrontp, "%d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ netprintf(" %d", pointer[i]);
}
break;
@@ -822,24 +881,19 @@ printsub(direction, pointer, length)
register char *cp;
register int j, k;
- sprintf(nfrontp, "STATUS");
- nfrontp += strlen(nfrontp);
+ netputs("STATUS");
switch (pointer[1]) {
default:
if (pointer[1] == TELQUAL_SEND)
- sprintf(nfrontp, " SEND");
+ netputs(" SEND");
else
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf(" %d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
case TELQUAL_IS:
- sprintf(nfrontp, " IS\r\n");
- nfrontp += strlen(nfrontp);
+ netputs(" IS\r\n");
for (i = 2; i < length; i++) {
switch(pointer[i]) {
@@ -849,19 +903,19 @@ printsub(direction, pointer, length)
case WONT: cp = "WONT"; goto common2;
common2:
i++;
+ netputs(" ");
+ netputs(cp);
+ netputs(" ");
if (TELOPT_OK(pointer[i]))
- sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i]));
+ netputs(TELOPT(pointer[i]));
else
- sprintf(nfrontp, " %s %d", cp, pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", pointer[i]);
- sprintf(nfrontp, "\r\n");
- nfrontp += strlen(nfrontp);
+ netputs("\r\n");
break;
case SB:
- sprintf(nfrontp, " SB ");
- nfrontp += strlen(nfrontp);
+ netputs(" SB ");
i++;
j = k = i;
while (j < length) {
@@ -877,20 +931,17 @@ printsub(direction, pointer, length)
}
printsub(0, &pointer[i], k - i);
if (i < length) {
- sprintf(nfrontp, " SE");
- nfrontp += strlen(nfrontp);
+ netputs(" SE");
i = j;
} else
i = j - 1;
- sprintf(nfrontp, "\r\n");
- nfrontp += strlen(nfrontp);
+ netputs("\r\n");
break;
default:
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d", pointer[i]);
break;
}
}
@@ -900,86 +951,79 @@ printsub(direction, pointer, length)
}
case TELOPT_XDISPLOC:
- sprintf(nfrontp, "X-DISPLAY-LOCATION ");
- nfrontp += strlen(nfrontp);
+ netputs("X-DISPLAY-LOCATION ");
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ netputs("IS \"");
+ netwrite((char *)pointer + 2, (size_t)(length - 2));
+ netputs("\"");
break;
case TELQUAL_SEND:
- sprintf(nfrontp, "SEND");
+ netputs("SEND");
break;
default:
- sprintf(nfrontp, "- unknown qualifier %d (0x%x).",
- pointer[1], pointer[1]);
+ netprintf("- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
}
- nfrontp += strlen(nfrontp);
break;
case TELOPT_NEW_ENVIRON:
- sprintf(nfrontp, "NEW-ENVIRON ");
+ netputs("NEW-ENVIRON ");
goto env_common1;
case TELOPT_OLD_ENVIRON:
- sprintf(nfrontp, "OLD-ENVIRON");
+ netputs("OLD-ENVIRON ");
env_common1:
- nfrontp += strlen(nfrontp);
switch (pointer[1]) {
case TELQUAL_IS:
- sprintf(nfrontp, "IS ");
+ netputs("IS ");
goto env_common;
case TELQUAL_SEND:
- sprintf(nfrontp, "SEND ");
+ netputs("SEND ");
goto env_common;
case TELQUAL_INFO:
- sprintf(nfrontp, "INFO ");
+ netputs("INFO ");
env_common:
- nfrontp += strlen(nfrontp);
{
register int noquote = 2;
for (i = 2; i < length; i++ ) {
switch (pointer[i]) {
case NEW_ENV_VAR:
- sprintf(nfrontp, "\" VAR " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" VAR " + noquote);
noquote = 2;
break;
case NEW_ENV_VALUE:
- sprintf(nfrontp, "\" VALUE " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" VALUE " + noquote);
noquote = 2;
break;
case ENV_ESC:
- sprintf(nfrontp, "\" ESC " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" ESC " + noquote);
noquote = 2;
break;
case ENV_USERVAR:
- sprintf(nfrontp, "\" USERVAR " + noquote);
- nfrontp += strlen(nfrontp);
+ netputs("\" USERVAR " + noquote);
noquote = 2;
break;
default:
if (isprint(pointer[i]) && pointer[i] != '"') {
if (noquote) {
- *nfrontp++ = '"';
+ netputs("\"");
noquote = 0;
}
- *nfrontp++ = pointer[i];
+ netprintf("%c", pointer[i]);
} else {
- sprintf(nfrontp, "\" %03o " + noquote,
- pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("\" %03o " + noquote,
+ pointer[i]);
noquote = 2;
}
break;
}
}
if (!noquote)
- *nfrontp++ = '"';
+ netputs("\"");
break;
}
}
@@ -987,91 +1031,74 @@ printsub(direction, pointer, length)
#if defined(AUTHENTICATION)
case TELOPT_AUTHENTICATION:
- sprintf(nfrontp, "AUTHENTICATION");
- nfrontp += strlen(nfrontp);
+ netputs("AUTHENTICATION");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case TELQUAL_REPLY:
case TELQUAL_IS:
- sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ?
- "IS" : "REPLY");
- nfrontp += strlen(nfrontp);
+ netputs((pointer[1] == TELQUAL_IS) ? " IS " : " REPLY ");
if (AUTHTYPE_NAME_OK(pointer[2]))
- sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2]));
+ netputs(AUTHTYPE_NAME(pointer[2]));
else
- sprintf(nfrontp, "%d ", pointer[2]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d ", pointer[2]);
if (length < 3) {
- sprintf(nfrontp, "(partial suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(partial suboption??\?)");
break;
}
- sprintf(nfrontp, "%s|%s%s",
- ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
- "CLIENT" : "SERVER",
- ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
- "MUTUAL" : "ONE-WAY",
- ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON) ?
- "|ENCRYPT" : "");
- nfrontp += strlen(nfrontp);
+ netputs(((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT)
+ ? "CLIENT|" : "SERVER|");
+ netputs(((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ? "MUTUAL" : "ONE-WAY");
+ netputs(((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON)
+ ? "|ENCRYPT" : "");
auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
- sprintf(nfrontp, "%s", buf);
- nfrontp += strlen(nfrontp);
+ netputs(buf);
break;
case TELQUAL_SEND:
i = 2;
- sprintf(nfrontp, " SEND ");
- nfrontp += strlen(nfrontp);
+ netputs(" SEND ");
while (i < length) {
if (AUTHTYPE_NAME_OK(pointer[i]))
- sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i]));
+ netputs(AUTHTYPE_NAME(pointer[i]));
else
- sprintf(nfrontp, "%d ", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", pointer[i]);
+ netputs(" ");
if (++i >= length) {
- sprintf(nfrontp, "(partial suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs("(partial suboption??\?)");
break;
}
- sprintf(nfrontp, "%s|%s%s ",
- ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
- "CLIENT" : "SERVER",
- ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
- "MUTUAL" : "ONE-WAY",
- ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON) ?
- "|ENCRYPT" : "");
- nfrontp += strlen(nfrontp);
+ netputs(((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT)
+ ? "CLIENT|" : "SERVER|");
+ netputs(((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
+ ? "MUTUAL" : "ONE-WAY");
+ if ((pointer[3] & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_ON)
+ netputs("|ENCRYPT");
++i;
}
break;
case TELQUAL_NAME:
i = 2;
- sprintf(nfrontp, " NAME \"");
- nfrontp += strlen(nfrontp);
+ netputs(" NAME \"");
while (i < length) {
if (isprint(pointer[i]))
- *nfrontp++ = pointer[i++];
+ netprintf("%c", pointer[i++]);
else {
- sprintf(nfrontp, "\"%03o",pointer[i++]);
- nfrontp += strlen(nfrontp);
+ netprintf("\\%03o", pointer[i++]);
}
}
- *nfrontp++ = '"';
+ netputs("\"");
break;
default:
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " ?%d?", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (i = 2; i < length; i++)
+ netprintf(" ?%d?", pointer[i]);
break;
}
break;
@@ -1079,87 +1106,72 @@ printsub(direction, pointer, length)
#ifdef ENCRYPTION
case TELOPT_ENCRYPT:
- sprintf(nfrontp, "ENCRYPT");
- nfrontp += strlen(nfrontp);
+ netputs("ENCRYPT");
if (length < 2) {
- sprintf(nfrontp, " (empty suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (empty suboption??\?)");
break;
}
switch (pointer[1]) {
case ENCRYPT_START:
- sprintf(nfrontp, " START");
- nfrontp += strlen(nfrontp);
+ netputs(" START");
break;
case ENCRYPT_END:
- sprintf(nfrontp, " END");
- nfrontp += strlen(nfrontp);
+ netputs(" END");
break;
case ENCRYPT_REQSTART:
- sprintf(nfrontp, " REQUEST-START");
- nfrontp += strlen(nfrontp);
+ netputs(" REQUEST-START");
break;
case ENCRYPT_REQEND:
- sprintf(nfrontp, " REQUEST-END");
- nfrontp += strlen(nfrontp);
+ netputs(" REQUEST-END");
break;
case ENCRYPT_IS:
case ENCRYPT_REPLY:
- sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ?
- "IS" : "REPLY");
- nfrontp += strlen(nfrontp);
+ netputs((pointer[1] == ENCRYPT_IS)
+ ? " IS " : " REPLY ");
if (length < 3) {
- sprintf(nfrontp, " (partial suboption??\?)");
- nfrontp += strlen(nfrontp);
+ netputs(" (partial suboption??\?)");
break;
}
if (ENCTYPE_NAME_OK(pointer[2]))
- sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2]));
+ netputs(ENCTYPE_NAME(pointer[2]));
else
- sprintf(nfrontp, " %d (unknown)", pointer[2]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d (unknown)", pointer[2]);
+ netputs(" ");
encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
- sprintf(nfrontp, "%s", buf);
- nfrontp += strlen(nfrontp);
+ netputs(buf);
break;
case ENCRYPT_SUPPORT:
i = 2;
- sprintf(nfrontp, " SUPPORT ");
- nfrontp += strlen(nfrontp);
+ netputs(" SUPPORT ");
while (i < length) {
if (ENCTYPE_NAME_OK(pointer[i]))
- sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i]));
+ netputs(ENCTYPE_NAME(pointer[i]));
else
- sprintf(nfrontp, "%d ", pointer[i]);
- nfrontp += strlen(nfrontp);
+ netprintf("%d", pointer[i]);
+ netputs(" ");
i++;
}
break;
case ENCRYPT_ENC_KEYID:
- sprintf(nfrontp, " ENC_KEYID", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netputs(" ENC_KEYID");
goto encommon;
case ENCRYPT_DEC_KEYID:
- sprintf(nfrontp, " DEC_KEYID", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netputs(" DEC_KEYID");
goto encommon;
default:
- sprintf(nfrontp, " %d (unknown)", pointer[1]);
- nfrontp += strlen(nfrontp);
+ netprintf(" %d (unknown)", pointer[1]);
encommon:
- for (i = 2; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ for (i = 2; i < length; i++)
+ netprintf(" %d", pointer[i]);
break;
}
break;
@@ -1167,18 +1179,15 @@ printsub(direction, pointer, length)
default:
if (TELOPT_OK(pointer[0]))
- sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0]));
+ netputs(TELOPT(pointer[0]));
else
- sprintf(nfrontp, "%d (unknown)", pointer[i]);
- nfrontp += strlen(nfrontp);
- for (i = 1; i < length; i++) {
- sprintf(nfrontp, " %d", pointer[i]);
- nfrontp += strlen(nfrontp);
- }
+ netprintf("%d", pointer[0]);
+ netputs(" (unknown)");
+ for (i = 1; i < length; i++)
+ netprintf(" %d", pointer[i]);
break;
}
- sprintf(nfrontp, "\r\n");
- nfrontp += strlen(nfrontp);
+ netputs("\r\n");
}
/*
@@ -1194,32 +1203,25 @@ printdata(tag, ptr, cnt)
char xbuf[30];
while (cnt) {
- /* flush net output buffer if no room for new data) */
- if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
- netflush();
- }
-
/* add a line of output */
- sprintf(nfrontp, "%s: ", tag);
- nfrontp += strlen(nfrontp);
+ netputs(tag);
+ netputs(": ");
for (i = 0; i < 20 && cnt; i++) {
- sprintf(nfrontp, "%02x", *ptr);
- nfrontp += strlen(nfrontp);
+ netprintf("%02x", *ptr);
if (isprint(*ptr)) {
xbuf[i] = *ptr;
} else {
xbuf[i] = '.';
}
- if (i % 2) {
- *nfrontp = ' ';
- nfrontp++;
- }
+ if (i % 2)
+ netputs(" ");
cnt--;
ptr++;
}
xbuf[i] = '\0';
- sprintf(nfrontp, " %s\r\n", xbuf );
- nfrontp += strlen(nfrontp);
+ netputs(" ");
+ netputs(xbuf);
+ netputs("\r\n");
}
}
#endif /* DIAGNOSTICS */