int main(int argc, char *argv[]) { struct sockaddr_in from; int on = 1; socklen_t fromlen; #ifndef REALLY_SMALL_TELNETD register int ch; #endif #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; #if defined(ENCRYPT) nclearto = 0; #endif progname = *argv; #ifdef CRAY /* * Get number of pty's before trying to process options, * which may include changing pty range. */ highpty = getnpty(); #endif /* CRAY */ #ifndef REALLY_SMALL_TELNETD while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:")) != EOF) { switch(ch) { #ifdef AUTHENTICATE case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } break; #endif /* AUTHENTICATE */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef AUTHENTICATE case 'e': if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* AUTHENTICATE */ case 'h': hostinfo = 0; break; #if defined(CRAY) && defined(NEWINIT) case 'I': { extern char *gen_id; gen_id = optarg; break; } #endif /* defined(CRAY) && defined(NEWINIT) */ #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'L': loginprg = optarg; break; case 'n': keepalive = 0; break; #ifdef CRAY case 'r': { char *strchr(); char *c; /* * Allow the specification of alterations * to the pty search range. It is legal to * specify only one, and not change the * other from its default. */ c = strchr(optarg, '-'); if (c) { *c++ = '\0'; highpty = atoi(c); } if (*optarg != '\0') lowpty = atoi(optarg); if ((lowpty > highpty) || (lowpty < 0) || (highpty > 32767)) { usage(); /* NOT REACHED */ } break; } #endif /* CRAY */ #ifdef SecurID case 's': /* SecurID required */ require_SecurID = 1; break; #endif /* SecurID */ case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; #ifdef AUTHENTICATE case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATE */ default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; #endif #ifndef REALLY_SMALL_TELNETD if (debug) { int s, ns; size_t foo; struct servent *sp; static struct sockaddr_in sn = { AF_INET }; if (argc > 1) { usage(); /* NOT REACHED */ } else if (argc == 1) { if ((sp = getservbyname(*argv, "tcp"))!=NULL) { sn.sin_port = sp->s_port; } else { sn.sin_port = atoi(*argv); if ((int)sn.sin_port <= 0) { fprintf(stderr, "telnetd: %s: bad port #\n", *argv); usage(); /* NOT REACHED */ } sn.sin_port = htons((u_short)sn.sin_port); } } else { sp = getservbyname("telnet", "tcp"); if (sp == 0) { fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); exit(1); } sn.sin_port = sp->s_port; } s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("telnetd: socket");; exit(1); } (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) { perror("bind"); exit(1); } if (listen(s, 1) < 0) { perror("listen"); exit(1); } foo = sizeof(sn); ns = accept(s, (struct sockaddr *)&sn, &foo); if (ns < 0) { perror("accept"); exit(1); } (void) dup2(ns, 0); (void) close(ns); (void) close(s); #ifdef convex } else if (argc == 1) { ; /* VOID*/ /* Just ignore the host/port name */ #endif } else if (argc > 0) { usage(); /* NOT REACHED */ } #endif #ifndef REALLY_SMALL_TELNETD openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); #endif fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { fprintf(stderr, "%s: ", progname); perror("getpeername"); // _exit(1); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { /*syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");*/ } #if defined(IPPROTO_IP) && defined(IP_TOS) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) /*syslog(LOG_WARNING, "setsockopt (IP_TOS): %m")*/; } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = 0; doit(&from); /* NOTREACHED */ return 0; } /* end of main */
int main(int argc, char *argv[]) { struct sockaddr_storage from; int on = 1, fromlen; int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; #ifdef ENCRYPTION nclearto = 0; #endif /* ENCRYPTION */ /* * This initialization causes linemode to default to a configuration * that works on all telnet clients, including the FreeBSD client. * This is not quite the same as the telnet client issuing a "mode * character" command, but has most of the same benefits, and is * preferable since some clients (like usofts) don't have the * mode character command anyway and linemode breaks things. * The most notable symptom of fix is that csh "set filec" operations * like <ESC> (filename completion) and ^D (choices) keys now work * in telnet sessions and can be used more than once on the same line. * CR/LF handling is also corrected in some termio modes. This * change resolves problem reports bin/771 and bin/1037. */ linemode=1; /*Default to mode that works on bulk of clients*/ while ((ch = getopt(argc, argv, valid_opts)) != -1) { switch(ch) { #ifdef AUTHENTICATION case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { warnx("unknown authorization level for -a"); } break; #endif /* AUTHENTICATION */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef ENCRYPTION case 'e': if (strcmp(optarg, "debug") == 0) { extern int encrypt_debug_mode; encrypt_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* ENCRYPTION */ case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'k': #if defined(LINEMODE) && defined(KLUDGELINEMODE) lmodetype = NO_AUTOKLUDGE; #else /* ignore -k option if built without kludge linemode */ #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ break; case 'n': keepalive = 0; break; case 'p': altlogin = optarg; break; case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) warnx("%s%s%s", "bad TOS argument '", optarg, "'; will try to use default TOS"); #else warnx("TOS option unavailable; -S flag not supported"); #endif break; case 'u': utmp_len = (size_t)atoi(optarg); if (utmp_len >= sizeof(remote_hostname)) utmp_len = sizeof(remote_hostname) - 1; break; case 'U': registerd_host_only = 1; break; #ifdef AUTHENTICATION case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATION */ case '4': family = AF_INET; break; #ifdef INET6 case '6': family = AF_INET6; break; #endif default: warnx("%c: unknown option", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int s, ns, foo, error; const char *service = "telnet"; struct addrinfo hints, *res; if (argc > 1) { usage(); /* NOT REACHED */ } else if (argc == 1) service = *argv; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; error = getaddrinfo(NULL, service, &hints, &res); if (error) { errx(1, "tcp/%s: %s\n", service, gai_strerror(error)); if (error == EAI_SYSTEM) errx(1, "tcp/%s: %s\n", service, strerror(errno)); usage(); } s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) err(1, "socket"); (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (bind(s, res->ai_addr, res->ai_addrlen) < 0) err(1, "bind"); if (listen(s, 1) < 0) err(1, "listen"); foo = res->ai_addrlen; ns = accept(s, res->ai_addr, &foo); if (ns < 0) err(1, "accept"); (void) dup2(ns, 0); (void) close(ns); (void) close(s); #ifdef convex } else if (argc == 1) { ; /* VOID*/ /* Just ignore the host/port name */ #endif } else if (argc > 0) { usage(); /* NOT REACHED */ } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { warn("getpeername"); _exit(1); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(IPPROTO_IP) && defined(IP_TOS) if (from.ss_family == AF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = 0; doit((struct sockaddr *)&from); /* NOTREACHED */ return(0); } /* end of main */
int main(int argc, char **argv) { struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; int on = 1; socklen_t sa_size; int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos __attribute__ ((unused)) = -1; #endif #ifdef ENCRYPTION extern int des_check_key; des_check_key = 1; /* Kludge for Mac NCSA telnet 2.6 /bg */ #endif pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; progname = *argv; #ifdef ENCRYPTION nclearto = 0; #endif #ifdef _CRAY /* * Get number of pty's before trying to process options, * which may include changing pty range. */ highpty = getnpty(); #endif /* CRAY */ while ((ch = getopt(argc, argv, valid_opts)) != -1) { switch(ch) { #ifdef AUTHENTICATION case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "otp") == 0) { auth_level = 0; require_otp = 1; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } break; #endif /* AUTHENTICATION */ case 'B': /* BFTP mode is not supported any more */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ case 'g': gettyent = optarg; break; case 'k': /* Linemode is not supported any more */ case 'l': break; case 'n': keepalive = 0; break; #ifdef _CRAY case 'r': { char *strchr(); char *c; /* * Allow the specification of alterations * to the pty search range. It is legal to * specify only one, and not change the * other from its default. */ c = strchr(optarg, '-'); if (c) { *c++ = '\0'; highpty = atoi(c); } if (*optarg != '\0') lowpty = atoi(optarg); if ((lowpty > highpty) || (lowpty < 0) || (highpty > 32767)) { usage(); /* NOT REACHED */ } break; } #endif /* CRAY */ case 'S': #ifdef HAVE_PARSETOS if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; case 'u': { char *eptr; utmp_len = strtol(optarg, &eptr, 0); if (optarg == eptr) fprintf(stderr, "telnetd: unknown utmp len (%s)\n", optarg); break; } case 'U': registerd_host_only = 1; break; #ifdef AUTHENTICATION case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif case 'y': no_warn = 1; break; #ifdef AUTHENTICATION case 'z': log_unauth = 1; break; #endif /* AUTHENTICATION */ case 'L': new_login = optarg; break; default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc > 0) { usage(); /* NOT REACHED */ } #ifdef _SC_CRAY_SECURE_SYS secflag = sysconf(_SC_CRAY_SECURE_SYS); /* * Get socket's security label */ if (secflag) { socklen_t szss = sizeof(ss); int sock_multi; socklen_t szi = sizeof(int); memset(&dv, 0, sizeof(dv)); if (getsysv(&sysv, sizeof(struct sysv)) != 0) fatalperror(net, "getsysv"); /* * Get socket security label and set device values * {security label to be set on ttyp device} */ #ifdef SO_SEC_MULTI /* 8.0 code */ if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, (void *)&ss, &szss) < 0) || (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, (void *)&sock_multi, &szi) < 0)) fatalperror(net, "getsockopt"); else { dv.dv_actlvl = ss.ss_actlabel.lt_level; dv.dv_actcmp = ss.ss_actlabel.lt_compart; if (!sock_multi) { dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; dv.dv_valcmp = dv.dv_actcmp; } else { dv.dv_minlvl = ss.ss_minlabel.lt_level; dv.dv_maxlvl = ss.ss_maxlabel.lt_level; dv.dv_valcmp = ss.ss_maxlabel.lt_compart; } dv.dv_devflg = 0; } #else /* SO_SEC_MULTI */ /* 7.0 code */ if (getsockopt(0, SOL_SOCKET, SO_SECURITY, (void *)&ss, &szss) >= 0) { dv.dv_actlvl = ss.ss_slevel; dv.dv_actcmp = ss.ss_compart; dv.dv_minlvl = ss.ss_minlvl; dv.dv_maxlvl = ss.ss_maxlvl; dv.dv_valcmp = ss.ss_maxcmp; } #endif /* SO_SEC_MULTI */ } #endif /* _SC_CRAY_SECURE_SYS */ openlog("ddtelnetd", LOG_PID | LOG_ODELAY, LOG_LOCAL2); sa_size = sizeof (__ss); if (getpeername(STDIN_FILENO, sa, &sa_size) < 0) { fprintf(stderr, "%s: ", progname); perror("getpeername"); _exit(1); } if (keepalive && setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(IPPROTO_IP) && defined(IP_TOS) && defined(HAVE_SETSOCKOPT) { # ifdef HAVE_GETTOSBYNAME struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && sa->sa_family == AF_INET && (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS, (void *)&tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = STDIN_FILENO; doit(sa, sa_size); /* NOTREACHED */ return 0; } /* end of main */
int main (int argc, char *argv[], char *env[]) { struct sockaddr_storage from; int on = 1, fromlen; register int ch; #if defined(IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif initsetproctitle(argc, argv, env); pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; progname = *argv; while ((ch = getopt(argc, argv, valid_opts)) != EOF) { switch (ch) { case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; case 'g': gettyname = optarg; break; case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'L': loginprg = strdup (optarg); break; #if defined(LINEMODE) && defined(KLUDGELINEMODE) case 'k': lmodetype = NO_AUTOKLUDGE; break; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ case 'n': keepalive = 0; break; case 'S': #ifdef HAS_GETTOS if ((tos = parsetos (optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; case 'u': utmp_len = atoi(optarg); break; case 'U': registerd_host_only = 1; break; case '4': family = AF_INET; break; case '6': family = AF_INET6; break; default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int s, ns, foo, error; char *service = "telnet"; struct addrinfo hints, *res; if (argc > 1) { usage(); /* NOT REACHED */ } else if (argc == 1) service = *argv; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; error = getaddrinfo(NULL, service, &hints, &res); if (error) { fprintf(stderr, "tcp/%s: %s\n", service, gai_strerror(error)); exit(1); } s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { perror("telnetd: socket"); exit(1); } setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { perror ("bind"); exit (1); } if (listen (s, 1) < 0) { perror ("listen"); exit (1); } foo = res->ai_addrlen; ns = accept(s, res->ai_addr, &foo); if (ns < 0) { perror("accept"); exit(1); } dup2(ns, 0); close(ns); close(s); } else if (argc > 0) { usage(); /* NOT REACHED */ } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername (0, (struct sockaddr *)&from, &fromlen) < 0) { fprintf(stderr, "%s: ", progname); perror("getpeername"); _exit(1); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof (on)) < 0) syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); #if defined(IPPROTO_IP) && defined(IP_TOS) if (from.ss_family == AF_INET) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ net = 0; doit((struct sockaddr *)&from); /* NOTREACHED */ return 0; } /* end of main */
int main(int argc, char *argv[], char *env[]) { struct sockaddr_in from; int on = 1; socklen_t fromlen; register int ch; #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif initsetproctitle(argc, argv, env); pfrontp = pbackp = ptyobuf; netip = netibuf; nfrontp = nbackp = netobuf; #if defined(ENCRYPT) nclearto = 0; #endif progname = *argv; while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:")) != EOF) { switch(ch) { #ifdef AUTHENTICATE case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } break; #endif /* AUTHENTICATE */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef AUTHENTICATE case 'e': if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* AUTHENTICATE */ case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'L': loginprg = strdup(optarg); /* XXX what if strdup fails? */ break; case 'n': keepalive = 0; break; #ifdef SecurID case 's': /* SecurID required */ require_SecurID = 1; break; #endif /* SecurID */ case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; #ifdef AUTHENTICATE case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATE */ default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int s, ns; socklen_t foo; struct servent *sp; struct sockaddr_in sn; memset(&sn, 0, sizeof(sn)); sn.sin_family = AF_INET; if (argc > 1) { usage(); /* NOTREACHED */ } else if (argc == 1) { if ((sp = getservbyname(*argv, "tcp"))!=NULL) { sn.sin_port = sp->s_port; } else { int pt = atoi(*argv); if (pt <= 0) { fprintf(stderr, "telnetd: %s: bad port number\n", *argv); usage(); /* NOTREACHED */ } sn.sin_port = htons(pt); } } else { sp = getservbyname("telnet", "tcp"); if (sp == 0) { fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); exit(1); } sn.sin_port = sp->s_port; } s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("telnetd: socket");; exit(1); } (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) { perror("bind"); exit(1); } if (listen(s, 1) < 0) { perror("listen"); exit(1); } foo = sizeof(sn); ns = accept(s, (struct sockaddr *)&sn, &foo); if (ns < 0) { perror("accept"); exit(1); } (void) dup2(ns, 0); (void) close(ns); (void) close(s); } else if (argc > 0) { usage(); /* NOT REACHED */ } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { fprintf(stderr, "%s: ", progname); perror("getpeername"); _exit(1); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */ net = 0; doit(&from); /* NOTREACHED */ return 0; } /* end of main */
int main(int argc, char *argv[], char *env[]) { struct sockaddr_storage from; int on = 1; socklen_t fromlen; register int ch; int i; #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif initsetproctitle(argc, argv, env); pfrontp = pbackp = ptyobuf; netip = netibuf; #ifdef USE_SSL /* we need to know the fullpath to the location of the * certificate that we will be running with as we cannot * be sure of the cwd when we are launched */ sprintf(cert_filepath,"%s/%s",X509_get_default_cert_dir(), "telnetd.pem"); ssl_cert_file=cert_filepath; ssl_key_file=NULL; #endif /* USE_SSL */ while ((ch = getopt(argc, argv, "d:a:e:lhnNr:I:D:B:sS:a:X:L:z:")) != EOF) { switch(ch) { #ifdef USE_SSL case 'z': { char *origopt; origopt=strdup(optarg); optarg=strtok(origopt,","); while(optarg!=NULL) { if (strcmp(optarg, "debug") == 0 ) { ssl_debug_flag=1; } else if (strcmp(optarg, "ssl") == 0 ) { ssl_only_flag=1; } else if (strcmp(optarg, "certsok") == 0 ) { ssl_certsok_flag=1; } else if ( (strcmp(optarg, "!ssl") == 0) || (strcmp(optarg, "nossl") == 0) ) { /* we may want to switch SSL negotiation off * for testing or other reasons */ ssl_disabled_flag=1; } else if (strcmp(optarg, "certrequired") == 0 ) { ssl_cert_required=1; } else if (strcmp(optarg, "secure") == 0 ) { ssl_secure_flag=1; } else if (strncmp(optarg, "verify=", strlen("verify=")) == 0 ) { ssl_verify_flag=atoi(optarg+strlen("verify=")); } else if (strncmp(optarg, "cert=", strlen("cert=")) == 0 ) { ssl_cert_file=optarg+strlen("cert="); } else if (strncmp(optarg, "key=", strlen("key=")) == 0 ) { ssl_key_file=optarg+strlen("key="); } else if (strncmp(optarg,"cipher=", strlen("cipher="))==0) { ssl_cipher_list=optarg+strlen("cipher="); } else { /* report when we are given rubbish so that * if the user makes a mistake they have to * correct it! */ fprintf(stderr,"Unknown SSL option %s\n",optarg); fflush(stderr); exit(1); } /* get the next one ... */ optarg=strtok(NULL,","); } /* if (origopt!=NULL) free(origopt); */ } break; #endif /* USE_SSL */ #ifdef AUTHENTICATE case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } break; #endif /* AUTHENTICATE */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef AUTHENTICATE case 'e': if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* AUTHENTICATE */ case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'L': loginprg = strdup(optarg); /* XXX what if strdup fails? */ break; case 'n': keepalive = 0; break; case 'N': numeric_hosts = 1; break; #ifdef SecurID case 's': /* SecurID required */ require_SecurID = 1; break; #endif /* SecurID */ case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; #ifdef AUTHENTICATE case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATE */ default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } #ifdef USE_SSL if (ssl_secure_flag || ssl_cert_required || ssl_certsok_flag) { /* in secure mode we *must* switch on the base level * verify checking otherwise we cannot abort connections * at the right place! */ if (ssl_verify_flag==0) ssl_verify_flag=1; } /* if we are not running in debug then any error * stuff from SSL debug *must* not go down * the socket (which 0,1,2 are all pointing to by * default) */ if (ssl_debug_flag) ssl_log_file="/telnetd.log"; if (!do_ssleay_init(1)) { if (bio_err!=NULL) { BIO_printf(bio_err,"do_ssleay_init() failed\n"); ERR_print_errors(bio_err); } else { fflush(stderr); fprintf(stderr,"do_ssleay_init() failed\n"); ERR_print_errors_fp(stderr); } exit(1); } if (ssl_debug_flag) { BIO_printf(bio_err,"secure %d certrequired %d verify %d\n", ssl_secure_flag,ssl_cert_required,ssl_verify_flag); for(i=0;i<argc;i++) BIO_printf(bio_err,"argv[%d]=\"%s\"\n",i,argv[i]); } #endif /* USE_SSL */ argc -= optind; argv += optind; if (debug) { if (argc > 1) { usage(); /* NOTREACHED */ } wait_for_connection((argc == 1) ? *argv : "telnet"); } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { fatalperror(2, "getpeername"); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */ #ifdef USE_SSL /* do the SSL stuff now ... before we play with pty's */ SSL_set_fd(ssl_con,0); if (ssl_only_flag) { /* hmm ... only when running talking to things like * https servers should we hit this code and then * we really don't care *who* we talk to :-) */ SSL_set_verify(ssl_con,ssl_verify_flag,NULL); if (SSL_accept(ssl_con) <= 0) { static char errbuf[1024]; sprintf(errbuf,"SSL_accept error %s\n", ERR_error_string(ERR_get_error(),NULL)); syslog(LOG_WARNING, "%s", errbuf); BIO_printf(bio_err,"%s",errbuf); /* go to sleep to make sure we are noticed */ sleep(10); SSL_free(ssl_con); _exit(1); } else { ssl_active_flag=1; } } #endif /* USE_SSL */ net = 0; netopen(); doit((struct sockaddr *)&from, fromlen); /* NOTREACHED */ return 0; } /* end of main */