?? telnetd.c
字號:
/* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * 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 lintstatic char copyright[] ="@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)telnetd.c 8.2 (Berkeley) 12/15/93";#endif /* not lint */#include "telnetd.h"#include "pathnames.h"#if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY)/* * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can * use it to tell us to turn off all the socket security code, * since that is only used in UNICOS 7.0 and later. */# undef _SC_CRAY_SECURE_SYS#endif#if defined(_SC_CRAY_SECURE_SYS)#include <sys/sysv.h>#include <sys/secdev.h># ifdef SO_SEC_MULTI /* 8.0 code */#include <sys/secparm.h>#include <sys/usrv.h># endif /* SO_SEC_MULTI */int secflag;char tty_dev[16];struct secdev dv;struct sysv sysv;# ifdef SO_SEC_MULTI /* 8.0 code */struct socksec ss;# else /* SO_SEC_MULTI */ /* 7.0 code */struct socket_security ss;# endif /* SO_SEC_MULTI */#endif /* _SC_CRAY_SECURE_SYS */#if defined(AUTHENTICATION)#include <libtelnet/auth.h>int auth_level = 0;#endif#if defined(SecurID)int require_SecurID = 0;#endifextern int utmp_len;int registerd_host_only = 0;#ifdef STREAMSPTY# include <stropts.h># include <termio.h>/* make sure we don't get the bsd version */# include "/usr/include/sys/tty.h"# include <sys/ptyvar.h>/* * Because of the way ptyibuf is used with streams messages, we need * ptyibuf+1 to be on a full-word boundary. The following wierdness * is simply to make that happen. */long ptyibufbuf[BUFSIZ/sizeof(long)+1];char *ptyibuf = ((char *)&ptyibufbuf[1])-1;char *ptyip = ((char *)&ptyibufbuf[1])-1;char ptyibuf2[BUFSIZ];unsigned char ctlbuf[BUFSIZ];struct strbuf strbufc, strbufd;int readstream();#else /* ! STREAMPTY *//* * I/O data buffers, * pointers, and counters. */char ptyibuf[BUFSIZ], *ptyip = ptyibuf;char ptyibuf2[BUFSIZ];#endif /* ! STREAMPTY */int hostinfo = 1; /* do we print login banner? */#ifdef CRAYextern int newmap; /* nonzero if \n maps to ^M^J */int lowpty = 0, highpty; /* low, high pty numbers */#endif /* CRAY */int debug = 0;int keepalive = 1;char *progname;extern void usage P((void));/* * The string to pass to getopt(). We do it this way so * that only the actual options that we support will be * passed off to getopt(). */char valid_opts[] = { 'd', ':', 'h', 'k', 'n', 'S', ':', 'u', ':', 'U',#ifdef AUTHENTICATION 'a', ':', 'X', ':',#endif#ifdef BFTPDAEMON 'B',#endif#ifdef DIAGNOSTICS 'D', ':',#endif#ifdef ENCRYPTION 'e', ':',#endif#if defined(CRAY) && defined(NEWINIT) 'I', ':',#endif#ifdef LINEMODE 'l',#endif#ifdef CRAY 'r', ':',#endif#ifdef SecurID 's',#endif '\0'};main(argc, argv) char *argv[];{ struct sockaddr_in from; int on = 1, fromlen; register int ch; extern char *optarg; extern int optind;#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 */ progname = *argv;#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)) != EOF) { 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 { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } 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;#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 '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;#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; case 'u': utmp_len = atoi(optarg); break; case 'U': registerd_host_only = 1; break;#ifdef AUTHENTICATION case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break;#endif /* AUTHENTICATION */ default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debug) { int s, ns, foo; struct servent *sp; static struct sockaddr_in sin = { AF_INET }; if (argc > 1) { usage(); /* NOT REACHED */ } else if (argc == 1) { if (sp = getservbyname(*argv, "tcp")) { sin.sin_port = sp->s_port; } else { sin.sin_port = atoi(*argv); if ((int)sin.sin_port <= 0) { fprintf(stderr, "telnetd: %s: bad port #\n", *argv); usage(); /* NOT REACHED */ } sin.sin_port = htons((u_short)sin.sin_port); } } else { sp = getservbyname("telnet", "tcp"); if (sp == 0) { fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); exit(1); } sin.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, (char *)&on, sizeof(on)); if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { perror("bind"); exit(1); } if (listen(s, 1) < 0) { perror("listen"); exit(1); } foo = sizeof sin; ns = accept(s, (struct sockaddr *)&sin, &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 */ }#if defined(_SC_CRAY_SECURE_SYS) secflag = sysconf(_SC_CRAY_SECURE_SYS); /* * Get socket's security label */ if (secflag) { int szss = sizeof(ss);#ifdef SO_SEC_MULTI /* 8.0 code */ int sock_multi; int szi = sizeof(int);#endif /* SO_SEC_MULTI */ bzero((char *)&dv, sizeof(dv)); if (getsysv(&sysv, sizeof(struct sysv)) != 0) { perror("getsysv"); exit(1); } /* * 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, (char *)&ss, &szss) < 0) || (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, (char *)&sock_multi, &szi) < 0)) { perror("getsockopt"); exit(1); } 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, (char *)&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("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 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(&from);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -