fix
[heimdal.git] / appl / telnet / telnetd / telnetd.c
blob779cb917c67b4f8c372cb93dcfe8215cf1ae4f5c
1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
31 * SUCH DAMAGE.
34 #include "telnetd.h"
36 RCSID("$Id$");
38 #ifdef _SC_CRAY_SECURE_SYS
39 #include <sys/sysv.h>
40 #include <sys/secdev.h>
41 #include <sys/secparm.h>
42 #include <sys/usrv.h>
43 int secflag;
44 char tty_dev[16];
45 struct secdev dv;
46 struct sysv sysv;
47 struct socksec ss;
48 #endif /* _SC_CRAY_SECURE_SYS */
50 #ifdef AUTHENTICATION
51 int auth_level = 0;
52 #endif
54 extern int utmp_len;
55 int registerd_host_only = 0;
57 #ifdef STREAMSPTY
58 # include <stropts.h>
59 # include <termios.h>
60 #ifdef HAVE_SYS_UIO_H
61 #include <sys/uio.h>
62 #endif /* HAVE_SYS_UIO_H */
63 #ifdef HAVE_SYS_STREAM_H
64 #include <sys/stream.h>
65 #endif
66 #ifdef _AIX
67 #include <sys/termio.h>
68 #endif
69 # ifdef HAVE_SYS_STRTTY_H
70 # include <sys/strtty.h>
71 # endif
72 # ifdef HAVE_SYS_STR_TTY_H
73 # include <sys/str_tty.h>
74 # endif
75 /* make sure we don't get the bsd version */
76 /* what is this here for? solaris? /joda */
77 # ifdef HAVE_SYS_TTY_H
78 # include "/usr/include/sys/tty.h"
79 # endif
80 # ifdef HAVE_SYS_PTYVAR_H
81 # include <sys/ptyvar.h>
82 # endif
85 * Because of the way ptyibuf is used with streams messages, we need
86 * ptyibuf+1 to be on a full-word boundary. The following wierdness
87 * is simply to make that happen.
89 long ptyibufbuf[BUFSIZ/sizeof(long)+1];
90 char *ptyibuf = ((char *)&ptyibufbuf[1])-1;
91 char *ptyip = ((char *)&ptyibufbuf[1])-1;
92 char ptyibuf2[BUFSIZ];
93 unsigned char ctlbuf[BUFSIZ];
94 struct strbuf strbufc, strbufd;
96 int readstream(int, char*, int);
98 #else /* ! STREAMPTY */
101 * I/O data buffers,
102 * pointers, and counters.
104 char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
105 char ptyibuf2[BUFSIZ];
107 #endif /* ! STREAMPTY */
109 int hostinfo = 1; /* do we print login banner? */
111 #ifdef _CRAY
112 extern int newmap; /* nonzero if \n maps to ^M^J */
113 int lowpty = 0, highpty; /* low, high pty numbers */
114 #endif /* CRAY */
116 int debug = 0;
117 int keepalive = 1;
118 char *progname;
120 extern void usage (void);
123 * The string to pass to getopt(). We do it this way so
124 * that only the actual options that we support will be
125 * passed off to getopt().
127 char valid_opts[] = "Bd:hklnS:u:UL:y"
128 #ifdef AUTHENTICATION
129 "a:X:z"
130 #endif
131 #ifdef DIAGNOSTICS
132 "D:"
133 #endif
134 #ifdef _CRAY
135 "r:"
136 #endif
139 void doit(struct sockaddr_in*);
141 int main(int argc, char **argv)
143 struct sockaddr_in from;
144 int on = 1, fromlen;
145 int ch;
146 #if defined(IPPROTO_IP) && defined(IP_TOS)
147 int tos = -1;
148 #endif
149 #ifdef ENCRYPTION
150 extern int des_check_key;
151 des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */
152 #endif
153 pfrontp = pbackp = ptyobuf;
154 netip = netibuf;
155 nfrontp = nbackp = netobuf;
157 progname = *argv;
158 #ifdef ENCRYPTION
159 nclearto = 0;
160 #endif
162 #ifdef _CRAY
164 * Get number of pty's before trying to process options,
165 * which may include changing pty range.
167 highpty = getnpty();
168 #endif /* CRAY */
170 while ((ch = getopt(argc, argv, valid_opts)) != EOF) {
171 switch(ch) {
173 #ifdef AUTHENTICATION
174 case 'a':
176 * Check for required authentication level
178 if (strcmp(optarg, "debug") == 0) {
179 auth_debug_mode = 1;
180 } else if (strcasecmp(optarg, "none") == 0) {
181 auth_level = 0;
182 } else if (strcasecmp(optarg, "otp") == 0) {
183 auth_level = 0;
184 require_otp = 1;
185 } else if (strcasecmp(optarg, "other") == 0) {
186 auth_level = AUTH_OTHER;
187 } else if (strcasecmp(optarg, "user") == 0) {
188 auth_level = AUTH_USER;
189 } else if (strcasecmp(optarg, "valid") == 0) {
190 auth_level = AUTH_VALID;
191 } else if (strcasecmp(optarg, "off") == 0) {
193 * This hack turns off authentication
195 auth_level = -1;
196 } else {
197 fprintf(stderr,
198 "telnetd: unknown authorization level for -a\n");
200 break;
201 #endif /* AUTHENTICATION */
203 case 'B': /* BFTP mode is not supported any more */
204 break;
205 case 'd':
206 if (strcmp(optarg, "ebug") == 0) {
207 debug++;
208 break;
210 usage();
211 /* NOTREACHED */
212 break;
214 #ifdef DIAGNOSTICS
215 case 'D':
217 * Check for desired diagnostics capabilities.
219 if (!strcmp(optarg, "report")) {
220 diagnostic |= TD_REPORT|TD_OPTIONS;
221 } else if (!strcmp(optarg, "exercise")) {
222 diagnostic |= TD_EXERCISE;
223 } else if (!strcmp(optarg, "netdata")) {
224 diagnostic |= TD_NETDATA;
225 } else if (!strcmp(optarg, "ptydata")) {
226 diagnostic |= TD_PTYDATA;
227 } else if (!strcmp(optarg, "options")) {
228 diagnostic |= TD_OPTIONS;
229 } else {
230 usage();
231 /* NOT REACHED */
233 break;
234 #endif /* DIAGNOSTICS */
237 case 'h':
238 hostinfo = 0;
239 break;
241 case 'k': /* Linemode is not supported any more */
242 case 'l':
243 break;
245 case 'n':
246 keepalive = 0;
247 break;
249 #ifdef _CRAY
250 case 'r':
252 char *strchr();
253 char *c;
256 * Allow the specification of alterations
257 * to the pty search range. It is legal to
258 * specify only one, and not change the
259 * other from its default.
261 c = strchr(optarg, '-');
262 if (c) {
263 *c++ = '\0';
264 highpty = atoi(c);
266 if (*optarg != '\0')
267 lowpty = atoi(optarg);
268 if ((lowpty > highpty) || (lowpty < 0) ||
269 (highpty > 32767)) {
270 usage();
271 /* NOT REACHED */
273 break;
275 #endif /* CRAY */
277 case 'S':
278 #ifdef HAVE_PARSETOS
279 if ((tos = parsetos(optarg, "tcp")) < 0)
280 fprintf(stderr, "%s%s%s\n",
281 "telnetd: Bad TOS argument '", optarg,
282 "'; will try to use default TOS");
283 #else
284 fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
285 "-S flag not supported\n");
286 #endif
287 break;
289 case 'u':
290 utmp_len = atoi(optarg);
291 break;
293 case 'U':
294 registerd_host_only = 1;
295 break;
297 #ifdef AUTHENTICATION
298 case 'X':
300 * Check for invalid authentication types
302 auth_disable_name(optarg);
303 break;
304 #endif
305 case 'y':
306 no_warn = 1;
307 break;
308 #ifdef AUTHENTICATION
309 case 'z':
310 log_unauth = 1;
311 break;
313 #endif /* AUTHENTICATION */
315 case 'L':
316 new_login = optarg;
317 break;
319 default:
320 fprintf(stderr, "telnetd: %c: unknown option\n", ch);
321 /* FALLTHROUGH */
322 case '?':
323 usage();
324 /* NOTREACHED */
328 argc -= optind;
329 argv += optind;
331 if (debug) {
332 int port = 0;
333 struct servent *sp;
335 if (argc > 1) {
336 usage ();
337 } else if (argc == 1) {
338 sp = roken_getservbyname (*argv, "tcp");
339 if (sp)
340 port = sp->s_port;
341 else
342 port = htons(atoi(*argv));
343 } else {
344 #ifdef KRB5
345 port = krb5_getportbyname (NULL, "telnet", "tcp", 23);
346 #else
347 port = k_getportbyname("telnet", "tcp", htons(23));
348 #endif
350 mini_inetd (port);
351 } else if (argc > 0) {
352 usage();
353 /* NOT REACHED */
356 #ifdef _SC_CRAY_SECURE_SYS
357 secflag = sysconf(_SC_CRAY_SECURE_SYS);
360 * Get socket's security label
362 if (secflag) {
363 int szss = sizeof(ss);
364 int sock_multi;
365 int szi = sizeof(int);
367 memset(&dv, 0, sizeof(dv));
369 if (getsysv(&sysv, sizeof(struct sysv)) != 0)
370 fatalperror(net, "getsysv");
373 * Get socket security label and set device values
374 * {security label to be set on ttyp device}
376 #ifdef SO_SEC_MULTI /* 8.0 code */
377 if ((getsockopt(0, SOL_SOCKET, SO_SECURITY,
378 (void *)&ss, &szss) < 0) ||
379 (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI,
380 (void *)&sock_multi, &szi) < 0))
381 fatalperror(net, "getsockopt");
382 else {
383 dv.dv_actlvl = ss.ss_actlabel.lt_level;
384 dv.dv_actcmp = ss.ss_actlabel.lt_compart;
385 if (!sock_multi) {
386 dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl;
387 dv.dv_valcmp = dv.dv_actcmp;
388 } else {
389 dv.dv_minlvl = ss.ss_minlabel.lt_level;
390 dv.dv_maxlvl = ss.ss_maxlabel.lt_level;
391 dv.dv_valcmp = ss.ss_maxlabel.lt_compart;
393 dv.dv_devflg = 0;
395 #else /* SO_SEC_MULTI */ /* 7.0 code */
396 if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
397 (void *)&ss, &szss) >= 0) {
398 dv.dv_actlvl = ss.ss_slevel;
399 dv.dv_actcmp = ss.ss_compart;
400 dv.dv_minlvl = ss.ss_minlvl;
401 dv.dv_maxlvl = ss.ss_maxlvl;
402 dv.dv_valcmp = ss.ss_maxcmp;
404 #endif /* SO_SEC_MULTI */
406 #endif /* _SC_CRAY_SECURE_SYS */
408 roken_openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
409 fromlen = sizeof (from);
410 if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
411 fprintf(stderr, "%s: ", progname);
412 perror("getpeername");
413 _exit(1);
415 if (keepalive &&
416 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
417 (void *)&on, sizeof (on)) < 0) {
418 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
421 #if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
423 # ifdef HAVE_GETTOSBYNAME
424 struct tosent *tp;
425 if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
426 tos = tp->t_tos;
427 # endif
428 if (tos < 0)
429 tos = 020; /* Low Delay bit */
430 if (tos
431 && (setsockopt(0, IPPROTO_IP, IP_TOS,
432 (void *)&tos, sizeof(tos)) < 0)
433 && (errno != ENOPROTOOPT) )
434 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
436 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
437 net = 0;
438 doit(&from);
439 /* NOTREACHED */
440 return 0;
441 } /* end of main */
443 void
444 usage()
446 fprintf(stderr, "Usage: telnetd");
447 #ifdef AUTHENTICATION
448 fprintf(stderr, " [-a (debug|other|otp|user|valid|off|none)]\n\t");
449 #endif
450 fprintf(stderr, " [-debug]");
451 #ifdef DIAGNOSTICS
452 fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
453 #endif
454 #ifdef AUTHENTICATION
455 fprintf(stderr, " [-edebug]");
456 #endif
457 fprintf(stderr, " [-h]");
458 fprintf(stderr, " [-L login]");
459 fprintf(stderr, " [-n]");
460 #ifdef _CRAY
461 fprintf(stderr, " [-r[lowpty]-[highpty]]");
462 #endif
463 fprintf(stderr, "\n\t");
464 #ifdef HAVE_GETTOSBYNAME
465 fprintf(stderr, " [-S tos]");
466 #endif
467 #ifdef AUTHENTICATION
468 fprintf(stderr, " [-X auth-type] [-y] [-z]");
469 #endif
470 fprintf(stderr, " [-u utmp_hostname_length] [-U]");
471 fprintf(stderr, " [port]\n");
472 exit(1);
476 * getterminaltype
478 * Ask the other end to send along its terminal type and speed.
479 * Output is the variable terminaltype filled in.
481 static unsigned char ttytype_sbbuf[] = {
482 IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
486 getterminaltype(char *name, size_t name_sz)
488 int retval = -1;
489 void _gettermname();
491 settimer(baseline);
492 #ifdef AUTHENTICATION
494 * Handle the Authentication option before we do anything else.
496 send_do(TELOPT_AUTHENTICATION, 1);
497 while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
498 ttloop();
499 if (his_state_is_will(TELOPT_AUTHENTICATION)) {
500 retval = auth_wait(name, name_sz);
502 #endif
504 #ifdef ENCRYPTION
505 send_will(TELOPT_ENCRYPT, 1);
506 send_do(TELOPT_ENCRYPT, 1); /* esc@magic.fi */
507 #endif
508 send_do(TELOPT_TTYPE, 1);
509 send_do(TELOPT_TSPEED, 1);
510 send_do(TELOPT_XDISPLOC, 1);
511 send_do(TELOPT_NEW_ENVIRON, 1);
512 send_do(TELOPT_OLD_ENVIRON, 1);
513 while (
514 #ifdef ENCRYPTION
515 his_do_dont_is_changing(TELOPT_ENCRYPT) ||
516 #endif
517 his_will_wont_is_changing(TELOPT_TTYPE) ||
518 his_will_wont_is_changing(TELOPT_TSPEED) ||
519 his_will_wont_is_changing(TELOPT_XDISPLOC) ||
520 his_will_wont_is_changing(TELOPT_NEW_ENVIRON) ||
521 his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) {
522 ttloop();
524 #ifdef ENCRYPTION
526 * Wait for the negotiation of what type of encryption we can
527 * send with. If autoencrypt is not set, this will just return.
529 if (his_state_is_will(TELOPT_ENCRYPT)) {
530 encrypt_wait();
532 #endif
533 if (his_state_is_will(TELOPT_TSPEED)) {
534 static unsigned char sb[] =
535 { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
537 telnet_net_write (sb, sizeof sb);
538 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
540 if (his_state_is_will(TELOPT_XDISPLOC)) {
541 static unsigned char sb[] =
542 { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
544 telnet_net_write (sb, sizeof sb);
545 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
547 if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
548 static unsigned char sb[] =
549 { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE };
551 telnet_net_write (sb, sizeof sb);
552 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
554 else if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
555 static unsigned char sb[] =
556 { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE };
558 telnet_net_write (sb, sizeof sb);
559 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
561 if (his_state_is_will(TELOPT_TTYPE)) {
563 telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);
564 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
565 sizeof ttytype_sbbuf - 2););
567 if (his_state_is_will(TELOPT_TSPEED)) {
568 while (sequenceIs(tspeedsubopt, baseline))
569 ttloop();
571 if (his_state_is_will(TELOPT_XDISPLOC)) {
572 while (sequenceIs(xdisplocsubopt, baseline))
573 ttloop();
575 if (his_state_is_will(TELOPT_NEW_ENVIRON)) {
576 while (sequenceIs(environsubopt, baseline))
577 ttloop();
579 if (his_state_is_will(TELOPT_OLD_ENVIRON)) {
580 while (sequenceIs(oenvironsubopt, baseline))
581 ttloop();
583 if (his_state_is_will(TELOPT_TTYPE)) {
584 char first[256], last[256];
586 while (sequenceIs(ttypesubopt, baseline))
587 ttloop();
590 * If the other side has already disabled the option, then
591 * we have to just go with what we (might) have already gotten.
593 if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
594 strcpy_truncate(first, terminaltype, sizeof(first));
595 for(;;) {
597 * Save the unknown name, and request the next name.
599 strcpy_truncate(last, terminaltype, sizeof(last));
600 _gettermname();
601 if (terminaltypeok(terminaltype))
602 break;
603 if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
604 his_state_is_wont(TELOPT_TTYPE)) {
606 * We've hit the end. If this is the same as
607 * the first name, just go with it.
609 if (strncmp(first, terminaltype, sizeof(first)) == 0)
610 break;
612 * Get the terminal name one more time, so that
613 * RFC1091 compliant telnets will cycle back to
614 * the start of the list.
616 _gettermname();
617 if (strncmp(first, terminaltype, sizeof(first)) != 0)
618 strcpy(terminaltype, first);
619 break;
624 return(retval);
625 } /* end of getterminaltype */
627 void
628 _gettermname()
631 * If the client turned off the option,
632 * we can't send another request, so we
633 * just return.
635 if (his_state_is_wont(TELOPT_TTYPE))
636 return;
637 settimer(baseline);
638 telnet_net_write (ttytype_sbbuf, sizeof ttytype_sbbuf);
639 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
640 sizeof ttytype_sbbuf - 2););
641 while (sequenceIs(ttypesubopt, baseline))
642 ttloop();
646 terminaltypeok(char *s)
648 return 1;
652 char *hostname;
653 char host_name[MaxHostNameLen];
654 char remote_host_name[MaxHostNameLen];
657 * Get a pty, scan input lines.
659 void
660 doit(struct sockaddr_in *who)
662 char *host = NULL;
663 struct hostent *hp;
664 int level;
665 int ptynum;
666 char user_name[256];
669 * Find an available pty to use.
671 ourpty = getpty(&ptynum);
672 if (ourpty < 0)
673 fatal(net, "All network ports in use");
675 #ifdef _SC_CRAY_SECURE_SYS
677 * set ttyp line security label
679 if (secflag) {
680 char slave_dev[16];
682 snprintf(tty_dev, sizeof(tty_dev), "/dev/pty/%03d", ptynum);
683 if (setdevs(tty_dev, &dv) < 0)
684 fatal(net, "cannot set pty security");
685 snprintf(slave_dev, sizeof(slave_dev), "/dev/ttyp%03d", ptynum);
686 if (setdevs(slave_dev, &dv) < 0)
687 fatal(net, "cannot set tty security");
689 #endif /* _SC_CRAY_SECURE_SYS */
691 /* get name of connected client */
692 hp = roken_gethostbyaddr((const char *)&who->sin_addr,
693 sizeof (struct in_addr),
694 who->sin_family);
696 if (hp == NULL && registerd_host_only) {
697 fatal(net, "Couldn't resolve your address into a host name.\r\n\
698 Please contact your net administrator");
699 } else if (hp) {
700 host = hp->h_name;
701 } else {
702 host = inet_ntoa(who->sin_addr);
705 * We must make a copy because Kerberos is probably going
706 * to also do a gethost* and overwrite the static data...
708 strcpy_truncate(remote_host_name, host, sizeof(remote_host_name));
709 host = remote_host_name;
711 /* XXX - should be k_gethostname? */
712 gethostname(host_name, sizeof (host_name));
713 hostname = host_name;
715 /* Only trim if too long (and possible) */
716 if (strlen(remote_host_name) > abs(utmp_len)) {
717 char *domain = strchr(host_name, '.');
718 char *p = strchr(remote_host_name, '.');
719 if (domain && p && (strcmp(p, domain) == 0))
720 *p = 0; /* remove domain part */
725 * If hostname still doesn't fit utmp, use ipaddr.
727 if (strlen(remote_host_name) > abs(utmp_len))
728 strcpy_truncate(remote_host_name,
729 inet_ntoa(who->sin_addr),
730 sizeof(remote_host_name));
732 #ifdef AUTHENTICATION
733 auth_encrypt_init(hostname, host, "TELNETD", 1);
734 #endif
736 init_env();
738 * get terminal type.
740 *user_name = 0;
741 level = getterminaltype(user_name, sizeof(user_name));
742 setenv("TERM", terminaltype ? terminaltype : "network", 1);
744 #ifdef _SC_CRAY_SECURE_SYS
745 if (secflag) {
746 if (setulvl(dv.dv_actlvl) < 0)
747 fatal(net,"cannot setulvl()");
748 if (setucmp(dv.dv_actcmp) < 0)
749 fatal(net, "cannot setucmp()");
751 #endif /* _SC_CRAY_SECURE_SYS */
753 /* begin server processing */
754 my_telnet(net, ourpty, host, level, user_name);
755 /*NOTREACHED*/
756 } /* end of doit */
758 /* output contents of /etc/issue.net, or /etc/issue */
759 static void
760 show_issue(void)
762 FILE *f;
763 char buf[128];
764 f = fopen("/etc/issue.net", "r");
765 if(f == NULL)
766 f = fopen("/etc/issue", "r");
767 if(f){
768 while(fgets(buf, sizeof(buf)-2, f)){
769 strcpy(buf + strcspn(buf, "\r\n"), "\r\n");
770 writenet((unsigned char*)buf, strlen(buf));
772 fclose(f);
777 * Main loop. Select from pty and network, and
778 * hand data to telnet receiver finite state machine.
780 void
781 my_telnet(int f, int p, char *host, int level, char *autoname)
783 int on = 1;
784 char *he;
785 char *IM;
786 int nfd;
787 int startslave_called = 0;
788 time_t timeout;
791 * Initialize the slc mapping table.
793 get_slc_defaults();
796 * Do some tests where it is desireable to wait for a response.
797 * Rather than doing them slowly, one at a time, do them all
798 * at once.
800 if (my_state_is_wont(TELOPT_SGA))
801 send_will(TELOPT_SGA, 1);
803 * Is the client side a 4.2 (NOT 4.3) system? We need to know this
804 * because 4.2 clients are unable to deal with TCP urgent data.
806 * To find out, we send out a "DO ECHO". If the remote system
807 * answers "WILL ECHO" it is probably a 4.2 client, and we note
808 * that fact ("WILL ECHO" ==> that the client will echo what
809 * WE, the server, sends it; it does NOT mean that the client will
810 * echo the terminal input).
812 send_do(TELOPT_ECHO, 1);
815 * Send along a couple of other options that we wish to negotiate.
817 send_do(TELOPT_NAWS, 1);
818 send_will(TELOPT_STATUS, 1);
819 flowmode = 1; /* default flow control state */
820 restartany = -1; /* uninitialized... */
821 send_do(TELOPT_LFLOW, 1);
824 * Spin, waiting for a response from the DO ECHO. However,
825 * some REALLY DUMB telnets out there might not respond
826 * to the DO ECHO. So, we spin looking for NAWS, (most dumb
827 * telnets so far seem to respond with WONT for a DO that
828 * they don't understand...) because by the time we get the
829 * response, it will already have processed the DO ECHO.
830 * Kludge upon kludge.
832 while (his_will_wont_is_changing(TELOPT_NAWS))
833 ttloop();
836 * But...
837 * The client might have sent a WILL NAWS as part of its
838 * startup code; if so, we'll be here before we get the
839 * response to the DO ECHO. We'll make the assumption
840 * that any implementation that understands about NAWS
841 * is a modern enough implementation that it will respond
842 * to our DO ECHO request; hence we'll do another spin
843 * waiting for the ECHO option to settle down, which is
844 * what we wanted to do in the first place...
846 if (his_want_state_is_will(TELOPT_ECHO) &&
847 his_state_is_will(TELOPT_NAWS)) {
848 while (his_will_wont_is_changing(TELOPT_ECHO))
849 ttloop();
852 * On the off chance that the telnet client is broken and does not
853 * respond to the DO ECHO we sent, (after all, we did send the
854 * DO NAWS negotiation after the DO ECHO, and we won't get here
855 * until a response to the DO NAWS comes back) simulate the
856 * receipt of a will echo. This will also send a WONT ECHO
857 * to the client, since we assume that the client failed to
858 * respond because it believes that it is already in DO ECHO
859 * mode, which we do not want.
861 if (his_want_state_is_will(TELOPT_ECHO)) {
862 DIAG(TD_OPTIONS,
863 {output_data("td: simulating recv\r\n");
865 willoption(TELOPT_ECHO);
869 * Finally, to clean things up, we turn on our echo. This
870 * will break stupid 4.2 telnets out of local terminal echo.
873 if (my_state_is_wont(TELOPT_ECHO))
874 send_will(TELOPT_ECHO, 1);
876 #ifdef TIOCPKT
877 #ifdef STREAMSPTY
878 if (!really_stream)
879 #endif
881 * Turn on packet mode
883 ioctl(p, TIOCPKT, (char *)&on);
884 #endif
888 * Call telrcv() once to pick up anything received during
889 * terminal type negotiation, 4.2/4.3 determination, and
890 * linemode negotiation.
892 telrcv();
894 ioctl(f, FIONBIO, (char *)&on);
895 ioctl(p, FIONBIO, (char *)&on);
897 #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
898 setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
899 (void *)&on, sizeof on);
900 #endif /* defined(SO_OOBINLINE) */
902 #ifdef SIGTSTP
903 signal(SIGTSTP, SIG_IGN);
904 #endif
905 #ifdef SIGTTOU
907 * Ignoring SIGTTOU keeps the kernel from blocking us
908 * in ttioct() in /sys/tty.c.
910 signal(SIGTTOU, SIG_IGN);
911 #endif
913 signal(SIGCHLD, cleanup);
915 #ifdef TIOCNOTTY
917 int t;
918 t = open(_PATH_TTY, O_RDWR);
919 if (t >= 0) {
920 ioctl(t, TIOCNOTTY, (char *)0);
921 close(t);
924 #endif
926 show_issue();
928 * Show banner that getty never gave.
930 * We put the banner in the pty input buffer. This way, it
931 * gets carriage return null processing, etc., just like all
932 * other pty --> client data.
935 if (getenv("USER"))
936 hostinfo = 0;
938 IM = DEFAULT_IM;
939 he = 0;
940 edithost(he, host_name);
941 if (hostinfo && *IM)
942 putf(IM, ptyibuf2);
944 if (pcc)
945 strncat(ptyibuf2, ptyip, pcc+1);
946 ptyip = ptyibuf2;
947 pcc = strlen(ptyip);
949 DIAG(TD_REPORT, {
950 output_data("td: Entering processing loop\r\n");
954 nfd = ((f > p) ? f : p) + 1;
955 timeout = time(NULL) + 5;
956 for (;;) {
957 fd_set ibits, obits, xbits;
958 int c;
960 /* wait for encryption to be turned on, but don't wait
961 indefinitely */
962 if(!startslave_called && (!encrypt_delay() || timeout > time(NULL))){
963 startslave_called = 1;
964 startslave(host, level, autoname);
967 if (ncc < 0 && pcc < 0)
968 break;
970 FD_ZERO(&ibits);
971 FD_ZERO(&obits);
972 FD_ZERO(&xbits);
974 * Never look for input if there's still
975 * stuff in the corresponding output buffer
977 if (nfrontp - nbackp || pcc > 0) {
978 FD_SET(f, &obits);
979 } else {
980 FD_SET(p, &ibits);
982 if (pfrontp - pbackp || ncc > 0) {
983 FD_SET(p, &obits);
984 } else {
985 FD_SET(f, &ibits);
987 if (!SYNCHing) {
988 FD_SET(f, &xbits);
990 if ((c = select(nfd, &ibits, &obits, &xbits,
991 (struct timeval *)0)) < 1) {
992 if (c == -1) {
993 if (errno == EINTR) {
994 continue;
997 sleep(5);
998 continue;
1002 * Any urgent data?
1004 if (FD_ISSET(net, &xbits)) {
1005 SYNCHing = 1;
1009 * Something to read from the network...
1011 if (FD_ISSET(net, &ibits)) {
1012 #ifndef SO_OOBINLINE
1014 * In 4.2 (and 4.3 beta) systems, the
1015 * OOB indication and data handling in the kernel
1016 * is such that if two separate TCP Urgent requests
1017 * come in, one byte of TCP data will be overlaid.
1018 * This is fatal for Telnet, but we try to live
1019 * with it.
1021 * In addition, in 4.2 (and...), a special protocol
1022 * is needed to pick up the TCP Urgent data in
1023 * the correct sequence.
1025 * What we do is: if we think we are in urgent
1026 * mode, we look to see if we are "at the mark".
1027 * If we are, we do an OOB receive. If we run
1028 * this twice, we will do the OOB receive twice,
1029 * but the second will fail, since the second
1030 * time we were "at the mark", but there wasn't
1031 * any data there (the kernel doesn't reset
1032 * "at the mark" until we do a normal read).
1033 * Once we've read the OOB data, we go ahead
1034 * and do normal reads.
1036 * There is also another problem, which is that
1037 * since the OOB byte we read doesn't put us
1038 * out of OOB state, and since that byte is most
1039 * likely the TELNET DM (data mark), we would
1040 * stay in the TELNET SYNCH (SYNCHing) state.
1041 * So, clocks to the rescue. If we've "just"
1042 * received a DM, then we test for the
1043 * presence of OOB data when the receive OOB
1044 * fails (and AFTER we did the normal mode read
1045 * to clear "at the mark").
1047 if (SYNCHing) {
1048 int atmark;
1050 ioctl(net, SIOCATMARK, (char *)&atmark);
1051 if (atmark) {
1052 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
1053 if ((ncc == -1) && (errno == EINVAL)) {
1054 ncc = read(net, netibuf, sizeof (netibuf));
1055 if (sequenceIs(didnetreceive, gotDM)) {
1056 SYNCHing = stilloob(net);
1059 } else {
1060 ncc = read(net, netibuf, sizeof (netibuf));
1062 } else {
1063 ncc = read(net, netibuf, sizeof (netibuf));
1065 settimer(didnetreceive);
1066 #else /* !defined(SO_OOBINLINE)) */
1067 ncc = read(net, netibuf, sizeof (netibuf));
1068 #endif /* !defined(SO_OOBINLINE)) */
1069 if (ncc < 0 && errno == EWOULDBLOCK)
1070 ncc = 0;
1071 else {
1072 if (ncc <= 0) {
1073 break;
1075 netip = netibuf;
1077 DIAG((TD_REPORT | TD_NETDATA), {
1078 output_data("td: netread %d chars\r\n", ncc);
1080 DIAG(TD_NETDATA, printdata("nd", netip, ncc));
1084 * Something to read from the pty...
1086 if (FD_ISSET(p, &ibits)) {
1087 #ifdef STREAMSPTY
1088 if (really_stream)
1089 pcc = readstream(p, ptyibuf, BUFSIZ);
1090 else
1091 #endif
1092 pcc = read(p, ptyibuf, BUFSIZ);
1095 * On some systems, if we try to read something
1096 * off the master side before the slave side is
1097 * opened, we get EIO.
1099 if (pcc < 0 && (errno == EWOULDBLOCK ||
1100 #ifdef EAGAIN
1101 errno == EAGAIN ||
1102 #endif
1103 errno == EIO)) {
1104 pcc = 0;
1105 } else {
1106 if (pcc <= 0)
1107 break;
1108 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
1109 netclear(); /* clear buffer back */
1110 #ifndef NO_URGENT
1112 * There are client telnets on some
1113 * operating systems get screwed up
1114 * royally if we send them urgent
1115 * mode data.
1117 output_data ("%c%c", IAC, DM);
1119 neturg = nfrontp-1; /* off by one XXX */
1120 DIAG(TD_OPTIONS,
1121 printoption("td: send IAC", DM));
1123 #endif
1125 if (his_state_is_will(TELOPT_LFLOW) &&
1126 (ptyibuf[0] &
1127 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
1128 int newflow =
1129 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
1130 if (newflow != flowmode) {
1131 flowmode = newflow;
1132 output_data("%c%c%c%c%c%c",
1133 IAC, SB, TELOPT_LFLOW,
1134 flowmode ? LFLOW_ON
1135 : LFLOW_OFF,
1136 IAC, SE);
1137 DIAG(TD_OPTIONS, printsub('>',
1138 (unsigned char *)nfrontp-4,
1139 4););
1142 pcc--;
1143 ptyip = ptyibuf+1;
1147 while (pcc > 0) {
1148 if ((&netobuf[BUFSIZ] - nfrontp) < 3)
1149 break;
1150 c = *ptyip++ & 0377, pcc--;
1151 if (c == IAC)
1152 *nfrontp++ = c;
1153 *nfrontp++ = c;
1154 if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
1155 if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
1156 *nfrontp++ = *ptyip++ & 0377;
1157 pcc--;
1158 } else
1159 *nfrontp++ = '\0';
1163 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
1164 netflush();
1165 if (ncc > 0)
1166 telrcv();
1167 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
1168 ptyflush();
1170 cleanup(0);
1173 #ifndef TCSIG
1174 # ifdef TIOCSIG
1175 # define TCSIG TIOCSIG
1176 # endif
1177 #endif
1179 #ifdef STREAMSPTY
1181 int flowison = -1; /* current state of flow: -1 is unknown */
1184 readstream(int p, char *ibuf, int bufsize)
1186 int flags = 0;
1187 int ret = 0;
1188 struct termios *tsp;
1189 #if 0
1190 struct termio *tp;
1191 #endif
1192 struct iocblk *ip;
1193 char vstop, vstart;
1194 int ixon;
1195 int newflow;
1197 strbufc.maxlen = BUFSIZ;
1198 strbufc.buf = (char *)ctlbuf;
1199 strbufd.maxlen = bufsize-1;
1200 strbufd.len = 0;
1201 strbufd.buf = ibuf+1;
1202 ibuf[0] = 0;
1204 ret = getmsg(p, &strbufc, &strbufd, &flags);
1205 if (ret < 0) /* error of some sort -- probably EAGAIN */
1206 return(-1);
1208 if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
1209 /* data message */
1210 if (strbufd.len > 0) { /* real data */
1211 return(strbufd.len + 1); /* count header char */
1212 } else {
1213 /* nothing there */
1214 errno = EAGAIN;
1215 return(-1);
1220 * It's a control message. Return 1, to look at the flag we set
1223 switch (ctlbuf[0]) {
1224 case M_FLUSH:
1225 if (ibuf[1] & FLUSHW)
1226 ibuf[0] = TIOCPKT_FLUSHWRITE;
1227 return(1);
1229 case M_IOCTL:
1230 ip = (struct iocblk *) (ibuf+1);
1232 switch (ip->ioc_cmd) {
1233 #ifdef TCSETS
1234 case TCSETS:
1235 case TCSETSW:
1236 case TCSETSF:
1237 tsp = (struct termios *)
1238 (ibuf+1 + sizeof(struct iocblk));
1239 vstop = tsp->c_cc[VSTOP];
1240 vstart = tsp->c_cc[VSTART];
1241 ixon = tsp->c_iflag & IXON;
1242 break;
1243 #endif
1244 #if 0
1245 case TCSETA:
1246 case TCSETAW:
1247 case TCSETAF:
1248 tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
1249 vstop = tp->c_cc[VSTOP];
1250 vstart = tp->c_cc[VSTART];
1251 ixon = tp->c_iflag & IXON;
1252 break;
1253 #endif
1254 default:
1255 errno = EAGAIN;
1256 return(-1);
1259 newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
1260 if (newflow != flowison) { /* it's a change */
1261 flowison = newflow;
1262 ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
1263 return(1);
1267 /* nothing worth doing anything about */
1268 errno = EAGAIN;
1269 return(-1);
1271 #endif /* STREAMSPTY */
1274 * Send interrupt to process on other side of pty.
1275 * If it is in raw mode, just write NULL;
1276 * otherwise, write intr char.
1278 void
1279 interrupt()
1281 ptyflush(); /* half-hearted */
1283 #if defined(STREAMSPTY) && defined(TIOCSIGNAL)
1284 /* Streams PTY style ioctl to post a signal */
1285 if (really_stream)
1287 int sig = SIGINT;
1288 ioctl(ourpty, TIOCSIGNAL, &sig);
1289 ioctl(ourpty, I_FLUSH, FLUSHR);
1291 #else
1292 #ifdef TCSIG
1293 ioctl(ourpty, TCSIG, (char *)SIGINT);
1294 #else /* TCSIG */
1295 init_termbuf();
1296 *pfrontp++ = slctab[SLC_IP].sptr ?
1297 (unsigned char)*slctab[SLC_IP].sptr : '\177';
1298 #endif /* TCSIG */
1299 #endif
1303 * Send quit to process on other side of pty.
1304 * If it is in raw mode, just write NULL;
1305 * otherwise, write quit char.
1307 void
1308 sendbrk()
1310 ptyflush(); /* half-hearted */
1311 #ifdef TCSIG
1312 ioctl(ourpty, TCSIG, (char *)SIGQUIT);
1313 #else /* TCSIG */
1314 init_termbuf();
1315 *pfrontp++ = slctab[SLC_ABORT].sptr ?
1316 (unsigned char)*slctab[SLC_ABORT].sptr : '\034';
1317 #endif /* TCSIG */
1320 void
1321 sendsusp()
1323 #ifdef SIGTSTP
1324 ptyflush(); /* half-hearted */
1325 # ifdef TCSIG
1326 ioctl(ourpty, TCSIG, (char *)SIGTSTP);
1327 # else /* TCSIG */
1328 *pfrontp++ = slctab[SLC_SUSP].sptr ?
1329 (unsigned char)*slctab[SLC_SUSP].sptr : '\032';
1330 # endif /* TCSIG */
1331 #endif /* SIGTSTP */
1335 * When we get an AYT, if ^T is enabled, use that. Otherwise,
1336 * just send back "[Yes]".
1338 void
1339 recv_ayt()
1341 #if defined(SIGINFO) && defined(TCSIG)
1342 if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
1343 ioctl(ourpty, TCSIG, (char *)SIGINFO);
1344 return;
1346 #endif
1347 output_data("\r\n[Yes]\r\n");
1350 void
1351 doeof()
1353 init_termbuf();
1355 *pfrontp++ = slctab[SLC_EOF].sptr ?
1356 (unsigned char)*slctab[SLC_EOF].sptr : '\004';