X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1c15e88899094343f75aeba04122cd96a96b428e..ad7871609881e73855d0b04da49b486cd93efca7:/usr/src/libexec/telnetd/utility.c diff --git a/usr/src/libexec/telnetd/utility.c b/usr/src/libexec/telnetd/utility.c index 43e6eb7ac3..d3b58edbf2 100644 --- a/usr/src/libexec/telnetd/utility.c +++ b/usr/src/libexec/telnetd/utility.c @@ -1,24 +1,38 @@ /* - * Copyright (c) 1989 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. * - * Redistribution and use in source and binary forms are permitted provided - * that: (1) source distributions retain this entire copyright notice and - * comment, and (2) distributions including binaries display the following - * acknowledgement: ``This product includes software developed by the - * University of California, Berkeley and its contributors'' in the - * documentation or other materials provided with the distribution and in - * all advertising materials mentioning features or use of this software. - * Neither the name of the University nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef lint -static char sccsid[] = "@(#)utility.c 5.4 (Berkeley) 6/28/90"; +static char sccsid[] = "@(#)utility.c 8.1 (Berkeley) 6/4/93"; #endif /* not lint */ #define PRINTOPTIONS @@ -37,17 +51,13 @@ static char sccsid[] = "@(#)utility.c 5.4 (Berkeley) 6/28/90"; * too full. */ -void + void ttloop() { void netflush(); -#ifdef DIAGNOSTICS - if (diagnostic & TD_REPORT) { - sprintf(nfrontp, "td: ttloop\r\n"); - nfrontp += strlen(nfrontp); - } -#endif /* DIAGNOSTICS */ + DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n"); + nfrontp += strlen(nfrontp);}); if (nfrontp-nbackp) { netflush(); } @@ -59,12 +69,8 @@ ttloop() syslog(LOG_INFO, "ttloop: peer died: %m\n"); exit(1); } -#ifdef DIAGNOSTICS - if (diagnostic & TD_REPORT) { - sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); - nfrontp += strlen(nfrontp); - } -#endif /* DIAGNOSTICS */ + DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); + nfrontp += strlen(nfrontp);}); netip = netibuf; telrcv(); /* state machine */ if (ncc > 0) { @@ -76,8 +82,9 @@ ttloop() /* * Check a descriptor to see if out of band data exists on it. */ + int stilloob(s) -int s; /* socket number */ + int s; /* socket number */ { static struct timeval timeout = { 0 }; fd_set excepts; @@ -99,24 +106,23 @@ int s; /* socket number */ } } + void ptyflush() { int n; if ((n = pfrontp - pbackp) > 0) { -#ifdef DIAGNOSTICS - if (diagnostic & (TD_REPORT | TD_PTYDATA)) { - sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); - nfrontp += strlen(nfrontp); - } - if (diagnostic & TD_PTYDATA) { - printdata("pd", pbackp, n); - } -#endif /* DIAGNOSTICS */ + DIAG((TD_REPORT | TD_PTYDATA), + { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); + nfrontp += strlen(nfrontp); }); + DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); n = write(pty, pbackp, n); } - if (n < 0) - return; + if (n < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) + return; + cleanup(0); + } pbackp += n; if (pbackp == pfrontp) pbackp = pfrontp = ptyobuf; @@ -132,9 +138,9 @@ ptyflush() * if the current address is a TELNET IAC ("I Am a Command") * character. */ -char * + char * nextitem(current) -char *current; + char *current; { if ((*current&0xff) != IAC) { return current+1; @@ -179,6 +185,7 @@ char *current; * caller should be setting the urgent data pointer AFTER calling * us in any case. */ + void netclear() { register char *thisitem, *next; @@ -186,7 +193,11 @@ netclear() #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) +#ifdef ENCRYPTION + thisitem = nclearto > netobuf ? nclearto : netobuf; +#else /* ENCRYPTION */ thisitem = netobuf; +#endif /* ENCRYPTION */ while ((next = nextitem(thisitem)) <= nbackp) { thisitem = next; @@ -194,7 +205,11 @@ netclear() /* Now, thisitem is first before/at boundary. */ +#ifdef ENCRYPTION + good = nclearto > netobuf ? nclearto : netobuf; +#else /* ENCRYPTION */ good = netobuf; /* where the good bytes go */ +#endif /* ENCRYPTION */ while (nfrontp > thisitem) { if (wewant(thisitem)) { @@ -223,20 +238,27 @@ 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) { -#ifdef DIAGNOSTICS - if (diagnostic & 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, + { sprintf(nfrontp, "td: netflush %d chars\r\n", n); + n += strlen(nfrontp); /* get count first */ + nfrontp += strlen(nfrontp); /* then move pointer */ + }); +#ifdef ENCRYPTION + if (encrypt_output) { + char *s = nclearto ? nclearto : nbackp; + if (nfrontp - s > 0) { + (*encrypt_output)((unsigned char *)s, nfrontp-s); + nclearto = nfrontp; + } } -#endif /* DIAGNOSTICS */ +#endif /* ENCRYPTION */ /* * if no urgent data, or if the other side appears to be an * old 4.2 client (and thus unable to survive TCP urgent data), @@ -264,14 +286,21 @@ netflush() if (n < 0) { if (errno == EWOULDBLOCK || errno == EINTR) return; - cleanup(); + cleanup(0); } nbackp += n; +#ifdef ENCRYPTION + if (nbackp > nclearto) + nclearto = 0; +#endif /* ENCRYPTION */ if (nbackp >= neturg) { neturg = 0; } if (nbackp == nfrontp) { nbackp = nfrontp = netobuf; +#ifdef ENCRYPTION + nclearto = 0; +#endif /* ENCRYPTION */ } return; } /* end of netflush */ @@ -287,9 +316,10 @@ netflush() * ptr - A pointer to a character string to write * len - How many bytes to write */ + void writenet(ptr, len) -register char *ptr; -register int len; + register unsigned char *ptr; + register int len; { /* flush buffer if no room for new data) */ if ((&netobuf[BUFSIZ] - nfrontp) < len) { @@ -308,6 +338,7 @@ register int len; */ + void fatal(f, msg) int f; char *msg; @@ -315,11 +346,22 @@ fatal(f, msg) char buf[BUFSIZ]; (void) sprintf(buf, "telnetd: %s.\r\n", msg); +#ifdef ENCRYPTION + if (encrypt_output) { + /* + * Better turn off encryption first.... + * Hope it flushes... + */ + encrypt_send_end(); + netflush(); + } +#endif /* ENCRYPTION */ (void) write(f, buf, (int)strlen(buf)); sleep(1); /*XXX*/ exit(1); } + void fatalperror(f, msg) int f; char *msg; @@ -332,6 +374,7 @@ fatalperror(f, msg) char editedhost[32]; + void edithost(pat, host) register char *pat; register char *host; @@ -374,27 +417,37 @@ edithost(pat, host) static char *putlocation; + void putstr(s) -register char *s; + register char *s; { while (*s) putchr(*s++); } + void putchr(cc) + int cc; { *putlocation++ = cc; } +/* + * This is split on two lines so that SCCS will not see the M + * between two % signs and expand it... + */ +static char fmtstr[] = { "%l:%M\ +%P on %A, %d %B %Y" }; + + void putf(cp, where) -register char *cp; -char *where; + register char *cp; + char *where; { char *slash; -#ifndef NO_GETTYTAB - char datebuffer[60]; -#endif /* NO_GETTYTAB */ + time_t t; + char db[100]; extern char *rindex(); putlocation = where; @@ -407,7 +460,12 @@ char *where; switch (*++cp) { case 't': +#ifdef STREAMSPTY + /* names are like /dev/pts/2 -- we want pts/2 */ + slash = index(line+1, '/'); +#else slash = rindex(line, '/'); +#endif if (slash == (char *) 0) putstr(line); else @@ -418,12 +476,11 @@ char *where; putstr(editedhost); break; -#ifndef NO_GETTYTAB case 'd': - get_date(datebuffer); - putstr(datebuffer); + (void)time(&t); + (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); + putstr(db); break; -#endif /* NO_GETTYTAB */ case '%': putchr('%'); @@ -433,31 +490,14 @@ char *where; } } -/*ARGSUSED*/ -#ifdef NO_GETTYTAB -getent(cp, name) -char *cp, *name; -{ - return(0); -} - -/*ARGSUSED*/ -char * -getstr(cp, cpp) -char *cp, **cpp; -{ - return(0); -} -#endif /* NO_GETTYTAB */ - #ifdef DIAGNOSTICS /* * Print telnet options and commands in plain text, if possible. */ -void + void printoption(fmt, option) -register char *fmt; -register int option; + register char *fmt; + register int option; { if (TELOPT_OK(option)) sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); @@ -469,18 +509,21 @@ register int option; return; } -char *slcnames[] = { SLC_NAMES }; - -void -printsub(dirp, pointer, length) -char *dirp; -unsigned char *pointer; /* where suboption data sits */ -int length; /* length of suboption data */ + void +printsub(direction, pointer, length) + char direction; /* '<' or '>' */ + unsigned char *pointer; /* where suboption data sits */ + int length; /* length of suboption data */ { register int i; + char buf[512]; + + if (!(diagnostic & TD_OPTIONS)) + return; - if (dirp) { - sprintf(nfrontp, "%s suboption ", dirp); + if (direction) { + sprintf(nfrontp, "td: %s suboption ", + direction == '<' ? "recv" : "send"); nfrontp += strlen(nfrontp); if (length >= 3) { register int j; @@ -570,10 +613,14 @@ int length; /* length of suboption data */ break; } switch (pointer[1]) { - case 0: + case LFLOW_OFF: sprintf(nfrontp, " OFF"); break; - case 1: + case LFLOW_ON: sprintf(nfrontp, " ON"); break; + case LFLOW_RESTART_ANY: + sprintf(nfrontp, " RESTART-ANY"); break; + case LFLOW_RESTART_XON: + sprintf(nfrontp, " RESTART-XON"); break; default: sprintf(nfrontp, " %d (unknown)", pointer[1]); } @@ -667,8 +714,8 @@ int length; /* length of suboption data */ sprintf(nfrontp, "SLC"); nfrontp += strlen(nfrontp); for (i = 2; i < length - 2; i += 3) { - if (pointer[i+SLC_FUNC] <= NSLC) - sprintf(nfrontp, " %s", slcnames[pointer[i+SLC_FUNC]]); + 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); @@ -774,7 +821,7 @@ int length; /* length of suboption data */ case WONT: cp = "WONT"; goto common2; common2: i++; - if (TELOPT_OK((int)pointer[i])) + if (TELOPT_OK(pointer[i])) sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); else sprintf(nfrontp, " %s %d", cp, pointer[i]); @@ -860,8 +907,6 @@ int length; /* length of suboption data */ for (i = 2; i < length; i++ ) { switch (pointer[i]) { case ENV_VAR: - if (pointer[1] == TELQUAL_SEND) - goto def_case; sprintf(nfrontp, "\" VAR " + noquote); nfrontp += strlen(nfrontp); noquote = 2; @@ -879,6 +924,12 @@ int length; /* length of suboption data */ noquote = 2; break; + case ENV_USERVAR: + sprintf(nfrontp, "\" USERVAR " + noquote); + nfrontp += strlen(nfrontp); + noquote = 2; + break; + default: def_case: if (isprint(pointer[i]) && pointer[i] != '"') { @@ -903,10 +954,183 @@ int length; /* length of suboption data */ } break; +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + sprintf(nfrontp, "AUTHENTICATION"); + nfrontp += strlen(nfrontp); + + if (length < 2) { + sprintf(nfrontp, " (empty suboption???)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case TELQUAL_REPLY: + case TELQUAL_IS: + sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ? + "IS" : "REPLY"); + nfrontp += strlen(nfrontp); + if (AUTHTYPE_NAME_OK(pointer[2])) + sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2])); + else + sprintf(nfrontp, "%d ", pointer[2]); + nfrontp += strlen(nfrontp); + if (length < 3) { + sprintf(nfrontp, "(partial suboption???)"); + nfrontp += strlen(nfrontp); + break; + } + sprintf(nfrontp, "%s|%s", + ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + nfrontp += strlen(nfrontp); + + auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + sprintf(nfrontp, "%s", buf); + nfrontp += strlen(nfrontp); + break; + + case TELQUAL_SEND: + i = 2; + sprintf(nfrontp, " SEND "); + nfrontp += strlen(nfrontp); + while (i < length) { + if (AUTHTYPE_NAME_OK(pointer[i])) + sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i])); + else + sprintf(nfrontp, "%d ", pointer[i]); + nfrontp += strlen(nfrontp); + if (++i >= length) { + sprintf(nfrontp, "(partial suboption???)"); + nfrontp += strlen(nfrontp); + break; + } + sprintf(nfrontp, "%s|%s ", + ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + nfrontp += strlen(nfrontp); + ++i; + } + break; + + case TELQUAL_NAME: + i = 2; + sprintf(nfrontp, " NAME \""); + nfrontp += strlen(nfrontp); + while (i < length) + *nfrontp += pointer[i++]; + *nfrontp += '"'; + break; + + default: + for (i = 2; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + sprintf(nfrontp, "ENCRYPT"); + nfrontp += strlen(nfrontp); + if (length < 2) { + sprintf(nfrontp, " (empty suboption???)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case ENCRYPT_START: + sprintf(nfrontp, " START"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_END: + sprintf(nfrontp, " END"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_REQSTART: + sprintf(nfrontp, " REQUEST-START"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_REQEND: + sprintf(nfrontp, " REQUEST-END"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_IS: + case ENCRYPT_REPLY: + sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ? + "IS" : "REPLY"); + nfrontp += strlen(nfrontp); + if (length < 3) { + sprintf(nfrontp, " (partial suboption???)"); + nfrontp += strlen(nfrontp); + break; + } + if (ENCTYPE_NAME_OK(pointer[2])) + sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2])); + else + sprintf(nfrontp, " %d (unknown)", pointer[2]); + nfrontp += strlen(nfrontp); + + encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + sprintf(nfrontp, "%s", buf); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_SUPPORT: + i = 2; + sprintf(nfrontp, " SUPPORT "); + nfrontp += strlen(nfrontp); + while (i < length) { + if (ENCTYPE_NAME_OK(pointer[i])) + sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i])); + else + sprintf(nfrontp, "%d ", pointer[i]); + nfrontp += strlen(nfrontp); + i++; + } + break; + + case ENCRYPT_ENC_KEYID: + sprintf(nfrontp, " ENC_KEYID", pointer[1]); + nfrontp += strlen(nfrontp); + goto encommon; + + case ENCRYPT_DEC_KEYID: + sprintf(nfrontp, " DEC_KEYID", pointer[1]); + nfrontp += strlen(nfrontp); + goto encommon; + + default: + sprintf(nfrontp, " %d (unknown)", pointer[1]); + nfrontp += strlen(nfrontp); + encommon: + for (i = 2; i < length; i++) { + sprintf(nfrontp, " %d", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + break; +#endif /* ENCRYPTION */ + default: - sprintf(nfrontp, "Unknown option "); + if (TELOPT_OK(pointer[0])) + sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0])); + else + sprintf(nfrontp, "%d (unknown)", pointer[i]); nfrontp += strlen(nfrontp); - for (i = 0; i < length; i++) { + for (i = 1; i < length; i++) { sprintf(nfrontp, " %d", pointer[i]); nfrontp += strlen(nfrontp); } @@ -919,14 +1143,14 @@ int length; /* length of suboption data */ /* * Dump a data buffer in hex and ascii to the output data stream. */ -void + void printdata(tag, ptr, cnt) -register char *tag; -register char *ptr; -register int cnt; + register char *tag; + register char *ptr; + register int cnt; { -register int i; -char xbuf[30]; + register int i; + char xbuf[30]; while (cnt) { /* flush net output buffer if no room for new data) */ @@ -957,15 +1181,4 @@ char xbuf[30]; nfrontp += strlen(nfrontp); } } - #endif /* DIAGNOSTICS */ - -#ifdef NO_STRERROR -char * -strerror(errno) -{ - extern char *sys_errlist[]; - - return(sys_errlist[errno]); -} -#endif