2
* Copyright (c) 1989 Regents of the University of California.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. All advertising materials mentioning features or use of this software
14
* must display the following acknowledgement:
15
* This product includes software developed by the University of
16
* California, Berkeley and its contributors.
17
* 4. Neither the name of the University nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
21
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
* From: @(#)utility.c 5.8 (Berkeley) 3/22/91
38
"$Id: utility.c,v 1.11 1999/12/12 14:59:45 dholland Exp $";
43
#include <sys/utsname.h>
47
#include <libtelnet/auth.h>
58
static struct buflist head = { next: &head, buf: 0, len: 0 };
59
static struct buflist *tail = &head;
62
static size_t listlen;
64
static struct buflist *urg;
76
* A small subroutine to flush the network output buffer, get some data
77
* from the network, and pass it through the telnet state machine. We
78
* also flush the pty input buffer (by dropping its data) if it becomes
86
DIAG(TD_REPORT, netoprintf("td: ttloop\r\n"););
89
ncc = read(net, netibuf, sizeof(netibuf));
91
syslog(LOG_INFO, "ttloop: read: %m\n");
93
} else if (ncc == 0) {
94
syslog(LOG_INFO, "ttloop: peer died: EOF\n");
97
DIAG(TD_REPORT, netoprintf("td: ttloop read %d chars\r\n", ncc););
99
telrcv(); /* state machine */
101
pfrontp = pbackp = ptyobuf;
104
} /* end of ttloop */
107
* Check a descriptor to see if out of band data exists on it.
109
int stilloob(int s) /* socket number */
111
static struct timeval timeout = { 0, 0 };
118
value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
119
} while ((value == -1) && (errno == EINTR));
122
fatalperror(pty, "select");
124
if (FD_ISSET(s, &excepts)) {
135
if ((n = pfrontp - pbackp) > 0) {
136
DIAG((TD_REPORT | TD_PTYDATA),
137
netoprintf("td: ptyflush %d chars\r\n", n););
138
DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
139
n = write(pty, pbackp, n);
142
if (errno == EWOULDBLOCK || errno == EINTR)
147
if (pbackp == pfrontp)
148
pbackp = pfrontp = ptyobuf;
154
* Return the address of the next "item" in the TELNET data
155
* stream. This will be the address of the next character if
156
* the current address is a user data character, or it will
157
* be the address of the character following the TELNET command
158
* if the current address is a TELNET IAC ("I Am a Command")
164
const unsigned char *current, const unsigned char *end,
165
const unsigned char *next, const unsigned char *nextend
167
if (*current++ != IAC) {
168
while (current < end && *current++ != IAC)
173
if (current >= end) {
182
switch (*current++) {
189
case SB: /* loop forever looking for the SE */
193
while (iac = 0, current < end) {
194
if (*current++ == IAC) {
195
if (current >= end) {
200
if (*current++ == SE) {
219
return next ? next + (current - end) : current;
220
} /* end of nextitem */
226
* We are about to do a TELNET SYNCH operation. Clear
227
* the path to the network.
229
* Things are a bit tricky since we may have sent the first
230
* byte or so of a previous TELNET command into the network.
231
* So, we have to scan the network buffer from the beginning
232
* until we are up to where we want to be.
234
* A side effect of what we do, just to keep things
235
* simple, is to clear the urgent data pointer. The principal
236
* caller should be setting the urgent data pointer AFTER calling
244
} /* end of netclear */
249
struct iovec *vector;
254
int ltrailing = trailing;
256
vector = malloc(listlen * sizeof(struct iovec));
261
len = listlen - (doclear & ltrailing);
264
while (lp != &head) {
268
n = send(net, lp->buf, 1, MSG_OOB);
276
v->iov_base = lp->buf;
277
v->iov_len = lp->len;
282
vector->iov_base = (char *)vector->iov_base + skip;
283
vector->iov_len -= skip;
285
n = writev(net, vector, len);
291
if (errno != EWOULDBLOCK && errno != EINTR)
299
while (lp->len <= len) {
300
if (lp == tail && ltrailing) {
306
head.next = lp->next;
323
* Send as much data as possible to the network,
324
* handling requests for urgent data.
329
if (fflush(netfile)) {
340
* miscellaneous functions doing a variety of little jobs follow ...
345
fatal(int f, const char *msg)
349
(void) snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg);
351
if (encrypt_output) {
353
* Better turn off encryption first....
360
(void) write(f, buf, (int)strlen(buf));
363
fprintf(stderr,"fatal called: %s\r\n",msg);
372
fatalperror(int f, const char *msg)
375
snprintf(buf, sizeof(buf), "%s: %s\r\n", msg, strerror(errno));
380
struct utsname kerninfo;
383
edithost(const char *pat, const char *host)
392
res = realloc(editedhost, strlen(pat) + strlen(host) + 1);
398
fprintf(stderr, "edithost: Out of memory\n");
423
(void) strcpy(res, host);
428
static char *putlocation;
432
putstr(const char *s)
434
while (*s) putchr(*s++);
442
static char fmtstr[] = { "%H:%M on %A, %d %B %Y" };
444
void putf(const char *cp, char *where)
461
slash = strrchr(line, '/');
470
/* output prog ver and SSLeay ver */
471
putstr("[SSL 0.10-");
472
putstr(SSLeay_version(SSLEAY_VERSION));
477
/* ignore the version token ... so we can have
478
* just the one version string which we hack
479
* here rather than all over the place
493
(void)strftime(db, sizeof(db), fmtstr, localtime(&t));
505
if (getdomainname(buff,sizeof(buff)) < 0
507
|| strcmp(buff, "(none)") == 0)
519
if ((fp = fopen(ISSUE_FILE, "r")) == NULL)
522
while ((c = fgetc(fp)) != EOF) {
523
if (p == '\n' && c == '#') {
526
} while (c != EOF && c != '\n');
528
} else if (c == '%') {
536
if (c == '\n') putchr('\r');
543
return; /* ignore remainder of the banner string */
547
putstr(kerninfo.sysname);
551
putstr(kerninfo.machine);
555
putstr(kerninfo.release);
560
putstr(kerninfo.version);
562
puts(kerninfo.version);
572
* Print telnet options and commands in plain text, if possible.
575
printoption(const char *fmt, int option)
577
if (TELOPT_OK(option))
578
netoprintf("%s %s\r\n", fmt, TELOPT(option));
579
else if (TELCMD_OK(option))
580
netoprintf("%s %s\r\n", fmt, TELCMD(option));
582
netoprintf("%s %d\r\n", fmt, option);
585
/* direction: '<' or '>' */
586
/* pointer: where suboption data sits */
587
/* length: length of suboption data */
589
printsub(char direction, unsigned char *pointer, int length)
596
if (!(diagnostic & TD_OPTIONS))
600
netoprintf("td: %s suboption ",
601
direction == '<' ? "recv" : "send");
605
i = pointer[length-2];
606
j = pointer[length-1];
608
if (i != IAC || j != SE) {
609
netoprintf("(terminated by ");
611
netoprintf("%s ", TELOPT(i));
612
else if (TELCMD_OK(i))
613
netoprintf("%s ", TELCMD(i));
615
netoprintf("%d ", i);
617
netoprintf("%s", TELOPT(j));
618
else if (TELCMD_OK(j))
619
netoprintf("%s", TELCMD(j));
622
netoprintf(", not IAC SE!) ");
628
netoprintf("(Empty suboption???)");
631
switch (pointer[0]) {
633
netoprintf("TERMINAL-TYPE ");
634
switch (pointer[1]) {
636
netoprintf("IS \"%.*s\"", length-2, (char *)pointer+2);
642
netoprintf("- unknown qualifier %d (0x%x).",
643
pointer[1], pointer[1]);
647
netoprintf("TERMINAL-SPEED");
649
netoprintf(" (empty suboption???)");
652
switch (pointer[1]) {
654
netoprintf(" IS %.*s", length-2, (char *)pointer+2);
660
netoprintf(" %d (unknown)", pointer[1]);
661
for (i = 2; i < length; i++) {
662
netoprintf(" ?%d?", pointer[i]);
669
netoprintf("TOGGLE-FLOW-CONTROL");
671
netoprintf(" (empty suboption???)");
674
switch (pointer[1]) {
676
netoprintf(" OFF"); break;
678
netoprintf(" ON"); break;
680
netoprintf(" %d (unknown)", pointer[1]);
682
for (i = 2; i < length; i++) {
683
netoprintf(" ?%d?", pointer[i]);
690
netoprintf(" (empty suboption???)");
694
netoprintf(" ?%d?", pointer[1]);
697
netoprintf(" %d %d (%d)",
698
pointer[1], pointer[2],
699
(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
701
netoprintf(" ?%d?", pointer[3]);
704
netoprintf(" %d %d (%d)",
705
pointer[3], pointer[4],
706
(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
707
for (i = 5; i < length; i++) {
708
netoprintf(" ?%d?", pointer[i]);
712
case TELOPT_LINEMODE:
713
netoprintf("LINEMODE ");
715
netoprintf(" (empty suboption???)");
718
switch (pointer[1]) {
732
netoprintf("(no option???)");
735
switch (pointer[2]) {
737
netoprintf("Forward Mask");
738
for (i = 3; i < length; i++) {
739
netoprintf(" %x", pointer[i]);
743
netoprintf("%d (unknown)", pointer[2]);
744
for (i = 3; i < length; i++) {
745
netoprintf(" %d", pointer[i]);
753
for (i = 2; i < length - 2; i += 3) {
754
if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
755
netoprintf(" %s", SLC_NAME(pointer[i+SLC_FUNC]));
757
netoprintf(" %d", pointer[i+SLC_FUNC]);
758
switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
760
netoprintf(" NOSUPPORT"); break;
762
netoprintf(" CANTCHANGE"); break;
764
netoprintf(" VARIABLE"); break;
766
netoprintf(" DEFAULT"); break;
769
pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
770
pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
771
pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
772
if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
773
SLC_FLUSHOUT| SLC_LEVELBITS)) {
774
netoprintf("(0x%x)", pointer[i+SLC_FLAGS]);
776
netoprintf(" %d;", pointer[i+SLC_VALUE]);
777
if ((pointer[i+SLC_VALUE] == IAC) &&
778
(pointer[i+SLC_VALUE+1] == IAC))
781
for (; i < length; i++) {
782
netoprintf(" ?%d?", pointer[i]);
789
netoprintf("(no mode???)");
794
snprintf(tbuf, sizeof(tbuf), "%s%s%s%s%s",
795
pointer[2]&MODE_EDIT ? "|EDIT" : "",
796
pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
797
pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
798
pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
799
pointer[2]&MODE_ACK ? "|ACK" : "");
800
netoprintf("%s", tbuf[1] ? &tbuf[1] : "0");
802
if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) {
803
netoprintf(" (0x%x)", pointer[2]);
805
for (i = 3; i < length; i++) {
806
netoprintf(" ?0x%x?", pointer[i]);
810
netoprintf("%d (unknown)", pointer[1]);
811
for (i = 2; i < length; i++) {
812
netoprintf(" %d", pointer[i]);
817
case TELOPT_STATUS: {
821
netoprintf("STATUS");
823
switch (pointer[1]) {
825
if (pointer[1] == TELQUAL_SEND)
828
netoprintf(" %d (unknown)", pointer[1]);
829
for (i = 2; i < length; i++) {
830
netoprintf(" ?%d?", pointer[i]);
834
netoprintf(" IS\r\n");
836
for (i = 2; i < length; i++) {
838
case DO: cp = "DO"; goto common2;
839
case DONT: cp = "DONT"; goto common2;
840
case WILL: cp = "WILL"; goto common2;
841
case WONT: cp = "WONT"; goto common2;
844
if (TELOPT_OK((int)pointer[i]))
845
netoprintf(" %s %s", cp, TELOPT(pointer[i]));
847
netoprintf(" %s %d", cp, pointer[i]);
857
if (pointer[j] == SE) {
860
if (pointer[j+1] == SE)
865
pointer[k++] = pointer[j++];
867
printsub(0, &pointer[i], k - i);
879
netoprintf(" %d", pointer[i]);
888
case TELOPT_XDISPLOC:
889
netoprintf("X-DISPLAY-LOCATION ");
890
switch (pointer[1]) {
892
netoprintf("IS \"%.*s\"", length-2, (char *)pointer+2);
898
netoprintf("- unknown qualifier %d (0x%x).",
899
pointer[1], pointer[1]);
904
netoprintf("ENVIRON ");
905
switch (pointer[1]) {
916
register int noquote = 2;
917
for (i = 2; i < length; i++ ) {
918
switch (pointer[i]) {
920
if (pointer[1] == TELQUAL_SEND)
922
netoprintf("\" VAR " + noquote);
927
netoprintf("\" VALUE " + noquote);
932
netoprintf("\" ESC " + noquote);
938
if (isprint(pointer[i]) && pointer[i] != '"') {
943
netoprintf("%c", pointer[i]);
945
netoprintf("\" %03o " + noquote,
959
#if defined(AUTHENTICATE)
960
case TELOPT_AUTHENTICATION:
961
netoprintf("AUTHENTICATION");
964
netoprintf(" (empty suboption???)");
967
switch (pointer[1]) {
970
netoprintf(" %s ", (pointer[1] == TELQUAL_IS) ?
972
if (AUTHTYPE_NAME_OK(pointer[2]))
973
netoprintf("%s ", AUTHTYPE_NAME(pointer[2]));
975
netoprintf("%d ", pointer[2]);
977
netoprintf("(partial suboption???)");
981
((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
983
((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
984
"MUTUAL" : "ONE-WAY");
986
auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
987
netoprintf("%s", buf);
992
netoprintf(" SEND ");
994
if (AUTHTYPE_NAME_OK(pointer[i]))
995
netoprintf("%s ", AUTHTYPE_NAME(pointer[i]));
997
netoprintf("%d ", pointer[i]);
999
netoprintf("(partial suboption???)");
1002
netoprintf("%s|%s ",
1003
((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
1004
"CLIENT" : "SERVER",
1005
((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
1006
"MUTUAL" : "ONE-WAY");
1013
netoprintf(" NAME \"");
1016
* while (i < length)
1017
* *nfrontp += pointer[i++];
1020
* but I'm pretty sure that's wrong...
1023
netoprintf("%c", pointer[i++]);
1028
for (i = 2; i < length; i++) {
1029
netoprintf(" ?%d?", pointer[i]);
1036
#if defined(ENCRYPT)
1037
case TELOPT_ENCRYPT:
1038
netoprintf("ENCRYPT");
1040
netoprintf(" (empty suboption???)");
1043
switch (pointer[1]) {
1045
netoprintf(" START");
1052
case ENCRYPT_REQSTART:
1053
netoprintf(" REQUEST-START");
1056
case ENCRYPT_REQEND:
1057
netoprintf(" REQUEST-END");
1062
netoprintf(" %s ", (pointer[1] == ENCRYPT_IS) ?
1065
netoprintf(" (partial suboption???)");
1068
if (ENCTYPE_NAME_OK(pointer[2]))
1069
netoprintf("%s ", ENCTYPE_NAME(pointer[2]));
1071
netoprintf(" %d (unknown)", pointer[2]);
1073
encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
1074
netoprintf("%s", buf);
1077
case ENCRYPT_SUPPORT:
1079
netoprintf(" SUPPORT ");
1080
while (i < length) {
1081
if (ENCTYPE_NAME_OK(pointer[i]))
1082
netoprintf("%s ", ENCTYPE_NAME(pointer[i]));
1084
netoprintf("%d ", pointer[i]);
1089
case ENCRYPT_ENC_KEYID:
1090
netoprintf(" ENC_KEYID", pointer[1]);
1093
case ENCRYPT_DEC_KEYID:
1094
netoprintf(" DEC_KEYID", pointer[1]);
1098
netoprintf(" %d (unknown)", pointer[1]);
1100
for (i = 2; i < length; i++) {
1101
netoprintf(" %d", pointer[i]);
1109
if (TELOPT_OK(pointer[0]))
1110
netoprintf("%s (unknown)", TELOPT(pointer[0]));
1112
netoprintf("%d (unknown)", pointer[i]);
1113
for (i = 1; i < length; i++) {
1114
netoprintf(" %d", pointer[i]);
1122
* Dump a data buffer in hex and ascii to the output data stream.
1125
printdata(const char *tag, const char *ptr, int cnt)
1131
/* add a line of output */
1132
netoprintf("%s: ", tag);
1133
for (i = 0; i < 20 && cnt; i++) {
1134
netoprintf("%02x", *ptr);
1135
if (isprint(*ptr)) {
1147
netoprintf(" %s\r\n", xbuf );
1150
#endif /* DIAGNOSTICS */
1152
static struct buflist *
1153
addbuf(const char *buf, size_t len)
1155
struct buflist *bufl;
1157
bufl = malloc(sizeof(struct buflist));
1161
bufl->next = tail->next;
1162
bufl->buf = malloc(len);
1169
tail = tail->next = bufl;
1172
memcpy(bufl->buf, buf, len);
1177
netwrite(void *cookie, const char *buf, size_t len)
1180
const char *const end = buf + len;
1181
int ltrailing = trailing;
1182
int ldoclear = doclear;
1184
#define wewant(p) ((*p&0xff) == IAC) && \
1185
((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)
1192
size_t m = tail->len;
1194
p = nextitem(tail->buf, tail->buf + tail->len, buf, end);
1202
tail->buf = realloc(tail->buf, tail->len);
1207
memcpy(tail->buf + m, buf, l);
1211
trailing = ltrailing;
1215
struct buflist *lpprev;
1229
if (lp == tail && ltrailing) {
1233
if (!wewant(lp->buf)) {
1234
lpprev->next = lp->next;
1248
p = nextitem(buf, end, 0, 0);
1252
} else if (ldoclear) {
1260
if (!addbuf(buf, l)) {
1261
return ret ? ret : -1;
1263
trailing = ltrailing;
1277
static const cookie_io_functions_t funcs = {
1278
read: 0, write: netwrite, seek: 0, close: 0
1281
netfile = fopencookie(0, "w", funcs);
1286
sendurg(const char *buf, size_t len) {
1288
fwrite(buf, 1, len, netfile);
1292
urg = addbuf(buf, len);
1296
netbuflen(int flush) {
1300
return listlen != 1 ? listlen : tail->len - skip;