📄 rlogin.c
字号:
/* * Copyright (c) 1983, 1990, 1993, 2002 * 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. * 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. *//* * rlogin - remote login */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#ifdef TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# ifdef HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#ifdef HAVE_SYS_RESOURCE_H#include <sys/resource.h>#endif#ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#include <sys/ioctl.h>#ifdef HAVE_SYS_STREAM_H#include <sys/stream.h>#endif#ifdef HAVE_SYS_TTY_H#include <sys/tty.h>#endif#ifdef HAVE_SYS_PTYVAR_H#include <sys/ptyvar.h>#endif#ifdef HAVE_SYS_SOCKIO_H#include <sys/sockio.h>#endif#include <netinet/in.h>#ifdef HAVE_NETINET_IN_SYSTM_H#include <netinet/in_systm.h>#endif#ifdef HAVE_NETINET_IP_H#include <netinet/ip.h>#endif#include <error.h>#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <netdb.h>#include <pwd.h>#include <setjmp.h>#include <termios.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#ifdef SHISHI#define REALM_SZ 1040#endif#if defined(KERBEROS) || defined(SHISHI)int use_kerberos = 1, doencrypt;#ifdef KERBEROS#include <kerberosIV/des.h>#include <kerberosIV/krb.h>char dest_realm_buf[REALM_SZ], *dest_realm = NULL;CREDENTIALS cred;Key_schedule schedule;# elif defined(SHISHI)# include <shishi.h># include "shishi_def.h"char dest_realm_buf[REALM_SZ], *dest_realm = NULL;Shishi * handle;Shishi_key * key;shishi_ivector iv1, iv2;shishi_ivector * ivtab[2];int keytype;int keylen;int rc;int wlen;#endif#endif /* KERBEROS *//* The TIOCPKT_* macros may not be implemented in the pty driver. Defining them here allows the program to be compiled. */#ifndef TIOCPKT# define TIOCPKT _IOW('t', 112, int)# define TIOCPKT_FLUSHWRITE 0x02# define TIOCPKT_NOSTOP 0x10# define TIOCPKT_DOSTOP 0x20#endif /*TIOCPKT*//* The server sends us a TIOCPKT_WINDOW notification when it starts up. The value for this (0x80) can not overlap the kernel defined TIOCPKT_xxx values. */#ifndef TIOCPKT_WINDOW#define TIOCPKT_WINDOW 0x80#endif/* Concession to Sun. */#ifndef SIGUSR1#define SIGUSR1 30#endif#ifndef _POSIX_VDISABLE# ifdef VDISABLE# define _POSIX_VDISABLE VDISABLE# else# define _POSIX_VDISABLE ((cc_t)'\377')# endif#endif/* Returned by speed() when the specified fd is not associated with a terminal. */#define SPEED_NOTATTY (-1)int eight=0, rem;int noescape;u_char escapechar = '~';#ifdef OLDSUNstruct winsize{ unsigned short ws_row; /* Rows, in characters. */ unsigned short ws_col; /* Columns , in characters. */ unsigned short ws_xpixel; /* Horizontal size, pixels. */ unsigned short ws_ypixel; /* Vertical size. pixels. */};int get_window_size (int, struct winsize *);#else# define get_window_size(fd, wp) ioctl (fd, TIOCGWINSZ, wp)#endifstruct winsize winsize;RETSIGTYPE catch_child (int);RETSIGTYPE copytochild (int);void doit (sigset_t *);void done (int);void echo (char);u_int getescape (char *);RETSIGTYPE lostpeer (int);void mode (int);void msg (const char *);RETSIGTYPE oob (int);int reader (sigset_t *);void sendwindow (void);void setsignal (int);int speed (int);unsigned int speed_translate (unsigned int);RETSIGTYPE sigwinch (int);void stop (char);void usage (int);void writer (void);RETSIGTYPE writeroob (int);#if defined(KERBEROS) || defined(SHISHI)void warning (const char *, ...);#endifextern sig_t setsig (int, sig_t);#if defined(KERBEROS) || defined(SHISHI)#define OPTIONS "8EKde:k:l:xhV"#else#define OPTIONS "8EKde:l:hV"#endifstatic const char *short_options = OPTIONS;static struct option long_options [] ={ { "debug", no_argument, 0, 'd' }, { "user", required_argument, 0, 'l' }, { "escape", required_argument, 0, 'e' }, { "no-escape", no_argument, 0, 'E' }, { "8-bit", no_argument, 0, '8' }, { "kerberos", no_argument, 0, 'K' },#if defined(KERBEROS) || defined(SHISHI) { "realm", required_argument, 0, 'k' }, { "encrypt", no_argument, 0, 'x' },#endif { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { NULL, 0, 0, 0}};char *program_name;intmain(int argc, char *argv[]){ struct passwd *pw; struct servent *sp; sigset_t smask; uid_t uid; int ch, dflag; int term_speed; char *host, *user, term[1024]; program_name = argv[0]; dflag = 0; host = user = NULL; /* Traditionnaly, if a symbolic link was made to the rlogin binary rlogin --> hostname hostname will be use as the name of the server to login too. */ { char *p = strrchr (argv[0], '/'); if (p) ++p; else p = argv[0]; if (strcmp (p, "rlogin") != 0) host = p; } while ((ch = getopt_long (argc, argv, short_options, long_options, NULL)) != EOF) { switch (ch) { /* 8-bit input Specifying this forces us to use RAW mode input from the user's terminal. Also, in this mode we won't perform any local flow control. */ case '8': eight = 1; break; case 'E': noescape = 1; break; case 'K':#if defined (KERBEROS) || defined(SHISHI) use_kerberos = 0;#endif break; /* Turn on the debug option for the socket. */ case 'd': dflag = 1; break; /* Specify an escape character, instead of the default tilde. */ case 'e': noescape = 0; escapechar = getescape (optarg); break;#if defined(KERBEROS) || defined(SHISHI) case 'k': strncpy (dest_realm_buf, optarg, sizeof dest_realm_buf); /* Make sure it's null termintated. */ dest_realm_buf[sizeof (dest_realm_buf) - 1] = '\0'; dest_realm = dest_realm_buf; break;#endif /* Specify the server-user-name, instead of using the name of the person invoking us. */ case 'l': user = optarg; break;#ifdef ENCRYPTION# if defined(KERBEROS) || defined (SHISHI) case 'x': doencrypt = 1;# if defined(KERBEROS) des_set_key (cred.session, schedule);#endif break;# endif#endif case 'V': printf ("rlogin (%s %s)\n", PACKAGE_NAME, PACKAGE_VERSION); exit (0); case '?': usage (1); break; case 'h': default: usage (0); } } if (optind < argc) host = argv[optind++]; argc -= optind; /* To many command line arguments or too few. */ if (argc > 0 || !host) usage (1); /* We must be uid root to access rcmd(). */ if (geteuid ()) error (1, 0, "must be setuid root.\n"); /* Get the name of the user invoking us: the client-user-name. */ if (!(pw = getpwuid (uid = getuid ()))) error (1, 0, "unknown user id."); /* Accept user1@host format, though "-l user2" overrides user1 */ { char *p = strchr (host, '@'); if (p) { *p = '\0'; if (!user && p > host) user = host; host = p + 1; if (*host == '\0') usage (1); } } sp = NULL;#if defined(KERBEROS) || defined(SHISHI) if (use_kerberos) { sp = getservbyname ((doencrypt ? "eklogin" : "klogin"), "tcp"); if (sp == NULL) { use_kerberos = 0; warning ("can't get entry for %s/tcp service", doencrypt ? "eklogin" : "klogin"); } }#endif /* Get the port number for the rlogin service. */ if (sp == NULL) sp = getservbyname ("login", "tcp"); if (sp == NULL) error (1, 0, "login/tcp: unknown service."); /* Get the name of the terminal from the environment. Also get the terminal's spee. Both the name and the spee are passed to the server as the "cmd" argument of the rcmd() function. This is something like "vt100/9600". */ term_speed = speed (0); if (term_speed == SPEED_NOTATTY) { char *p; snprintf (term, sizeof term, "%s", ((p = getenv ("TERM")) ? p : "network")); } else { char *p; snprintf (term, sizeof term, "%s/%d", ((p = getenv ("TERM")) ? p : "network"), term_speed); } get_window_size (0, &winsize); setsig (SIGPIPE, lostpeer); /* Block SIGURG and SIGUSR1 signals. This will be handled by the parent and the child after the fork. */ /* Will use SIGUSR1 for window size hack, so hold it off. */ sigemptyset (&smask); sigaddset (&smask, SIGURG); sigaddset (&smask, SIGUSR1); sigprocmask (SIG_SETMASK, &smask, &smask); /* * We set SIGURG and SIGUSR1 below so that an * incoming signal will be held pending rather than being * discarded. Note that these routines will be ready to get * a signal by the time that they are unblocked below. */ setsig (SIGURG, copytochild); setsig (SIGUSR1, writeroob);#if defined (KERBEROS) || defined(SHISHI) try_connect: if (use_kerberos) { struct hostent *hp; /* Fully qualify hostname (needed for krb_realmofhost). */ hp = gethostbyname (host); if (hp != NULL && !(host = strdup (hp->h_name))) error (1, errno, "strdup");#if defined (KERBEROS) rem = KSUCCESS; errno = 0; if (dest_realm == NULL) dest_realm = krb_realmofhost (host);#elif defined (SHISHI) rem = SHISHI_OK; errno = 0;#endif# ifdef ENCRYPTION if (doencrypt)#if defined(SHISHI) { int i; rem = krcmd_mutual (&handle, &host, sp->s_port, &user, term, 0, dest_realm, &key); if (rem > 0) { keytype = shishi_key_type (key); keylen = shishi_cipher_blocksize (keytype);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -