⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rlogind.c

📁 压缩包中包含LINUX下多个命令的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 1998,2001, 2002 Free Software Foundation, Inc.   This file is part of GNU Inetutils.   GNU Inetutils is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   GNU Inetutils is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with GNU Inetutils; see the file COPYING.  If not, write to   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA. */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <signal.h>#ifdef HAVE_SYS_FILIO_H# include <sys/filio.h>#endif#include <termios.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_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#include <sys/wait.h>#include <sys/socket.h>#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 <arpa/inet.h>#include <netdb.h>#include <pwd.h>#include <syslog.h>#include <errno.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#ifdef HAVE_SYS_SELECT_H# include <sys/select.h>#endif#include <sys/ioctl.h>#include <sys/stat.h> /* Needed for chmod() *//*  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*/#ifndef TIOCPKT_WINDOW# define TIOCPKT_WINDOW 0x80#endif/* `defaults' for tty settings.  */#ifndef TTYDEF_IFLAG#define	TTYDEF_IFLAG	(BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY)#endif#ifndef TTYDEF_OFLAG#ifndef OXTABS#define OXTABS 0#endif#define TTYDEF_OFLAG	(OPOST | ONLCR | OXTABS)#endif#ifndef TTYDEF_LFLAG#define TTYDEF_LFLAG	(ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)#endif#define AUTH_KERBEROS_4 4#define AUTH_KERBEROS_5 5#ifdef KERBEROS# define	SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"# ifdef	KERBEROS_IV#  include <kerberosIV/des.h>#  include <kerberosIV/krb.h>#  define kerberos_error_string(c) krb_err_txt[c]#  define AUTH_KERBEROS_DEFAULT AUTH_KERBEROS_4# elif defined(KERBEROS_V)#  include <krb5.h>#  include <kerberosIV/krb.h>#  define kerberos_error_string(c) error_message (c)#  define AUTH_KERBEROS_DEFAULT AUTH_KERBEROS_5# endif#endif /* KERBEROS */#define	ENVSIZE	(sizeof("TERM=")-1)	/* skip null for concatenation */#ifndef DEFMAXCHILDREN# define DEFMAXCHILDREN 10   /* Default maximum number of children */#endif#ifndef DEFPORT# define DEFPORT 513#endifextern int __check_rhosts_file;struct auth_data{  struct sockaddr_in from;  char *hostname;  char *lusername;  char *rusername;  char *term;  char *env[2];#ifdef KERBEROS#ifdef KERBEROS_V  int kerberos_version;  krb5_principal client;  krb5_context context;  krb5_ccache ccache;  krb5_keytab keytab;#endif#endif};static const char *short_options = "aD::d::hk::L:lnp:orxV";static struct option long_options[] ={  {"allow-root", no_argument, 0, 'o'},  {"verify-hostname", no_argument, 0, 'a'},  {"daemon", optional_argument, 0, 'd'},  {"no-rhosts", no_argument, 0, 'l'},  {"no-keepalive", no_argument, 0, 'n'},  {"local-domain", required_argument, 0, 'L'},  {"kerberos", optional_argument, 0, 'k'},  {"encrypt", no_argument, 0, 'x'},  {"debug", optional_argument, 0, 'D'},  {"help", no_argument, 0, 'h'},  {"version", no_argument, 0, 'V'},  {"port", required_argument, 0, 'p'},  {"reverse-required", no_argument, 0, 'r'},  {0, 0, 0, 0}};int allow_root = 0;int verify_hostname = 0;int keepalive = 1;#ifdef KERBEROSint kerberos = 0;#ifdef ENCRYPTIONint encrypt_io = 0;#endif /* ENCRYPTION */#endif /* KERBEROS */int reverse_required = 0;int debug_level = 0;int numchildren;int netf;char line[1024];		/* FIXME */int confirmed;const char *path_login = PATH_LOGIN;char *local_domain_name;int local_dot_count;struct winsize win = {0, 0, 0, 0};void usage __P ((void));void rlogin_daemon __P ((int maxchildren, int port));int rlogind_auth __P ((int fd, struct auth_data *ap));void setup_tty __P ((int fd, struct auth_data *ap));void exec_login __P ((int authenticated, struct auth_data *ap));int rlogind_mainloop __P ((int infd, int outfd));int do_rlogin __P ((int infd, struct auth_data *ap));int do_krb_login __P ((int infd, struct auth_data *ap, const char **msg));void getstr __P ((int infd, char **ptr, const char *prefix));void protocol __P ((int f, int p));int control __P ((int pty, char *cp, size_t n));RETSIGTYPE cleanup __P ((int signo));void fatal __P ((int f, const char *msg, int syserr));int in_local_domain __P ((char *hostname));char *topdomain __P ((char *name, int max_dots));RETSIGTYPErlogind_sigchld (int sig){  pid_t pid;  int status;  while ((pid = waitpid (-1, &status, WNOHANG)) > 0)    --numchildren;  signal (sig, rlogind_sigchld);}#define MODE_INETD 0#define MODE_DAEMON 1#if defined(KERBEROS) && defined(ENCRYPTION)# define ENCRYPT_IO encrypt_io# define IF_ENCRYPT(stmt) if (encrypt_io) stmt# define IF_NOT_ENCRYPT(stmt) if (!encrypt_io) stmt# define ENC_READ(c, fd, buf, size) \ if (encrypt_io) \     c = des_read(fd, buf, size); \ else \     c = read(fd, buf, size);# define ENC_WRITE(c, fd, buf, size) \ if (encrypt_io) \     c = des_write(fd, buf, size); \ else \     c = write(fd, buf, size);#else# define ENCRYPT_IO 0# define IF_ENCRYPT(stmt)# define IF_NOT_ENCRYPT(stmt) stmt# define ENC_READ(c, fd, buf, size) c = read (fd, buf, size)# define ENC_WRITE(c, fd, buf, size) c = write (fd, buf, size)#endifintmain (int argc, char *argv[]){  int port = 0;  int maxchildren = DEFMAXCHILDREN;  int mode = MODE_INETD;  int c;  while ((c = getopt_long (argc, argv, short_options, long_options, NULL))	 != EOF)    {      switch (c)	{	case 'a':	  verify_hostname = 1;	  break;	case 'D':	  if (optarg)	    debug_level = strtoul (optarg, NULL, 10);	  break;	case 'd':	  mode = MODE_DAEMON;	  if (optarg)	    maxchildren = strtoul (optarg, NULL, 10);	  if (maxchildren == 0)	    maxchildren = DEFMAXCHILDREN;	  break;	case 'l':	  __check_rhosts_file = 0; /* FIXME: extern var? */	  break;	case 'L':	  local_domain_name = optarg;	  break;	case 'n':	  keepalive = 0;	  break;#ifdef KERBEROS	case 'k':	  if (optarg)	    {	      if (*optarg == '4')		kerberos = AUTH_KERBEROS_4;	      else if (*optarg == '5')		kerberos = AUTH_KERBEROS_5;	    }	  else	    kerberos = AUTH_KERBEROS_DEFAULT;	  break;# ifdef ENCRYPTION	case 'x':	  encrypt_io = 1;	  break;# endif /* ENCRYPTION */#endif /* KERBEROS */	case 'o':	  allow_root = 1;	  break;	case 'p':	  port = strtoul (optarg, NULL, 10);	  break;	case 'r':	  reverse_required = 1;	  break;	case 'V':	  printf ("rlogind (%s %s)\n", PACKAGE_NAME, PACKAGE_VERSION);	  exit (0);	case 'h':	default:	  usage ();	  exit (0);	}    }  openlog ("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);  argc -= optind;  if (argc > 0)    {      syslog (LOG_ERR, "%d extra arguments", argc);      exit (1);    }  signal (SIGHUP, SIG_IGN);  if (!local_domain_name)    {      char *p = localhost ();      if (!p)	{	  syslog (LOG_ERR, "can't determine local hostname");	  exit (1);	}      local_dot_count = 2;      local_domain_name = topdomain (p, local_dot_count);    }  else    {      char *p;      local_dot_count = 0;      for (p = local_domain_name; *p; p++)	if (*p == '.')	  local_dot_count++;    }  if (mode == MODE_DAEMON)    rlogin_daemon (maxchildren, port);  else    exit (rlogind_mainloop (fileno (stdin), fileno (stdout)));  /* To pacify lint */  return 0;}voidrlogin_daemon (int maxchildren, int port){  pid_t pid;  size_t size;  struct sockaddr_in saddr;  int listenfd, fd;  if (port == 0)    {      struct servent *svp;      svp = getservbyname ("login", "tcp");      if (svp != NULL)	port = ntohs (svp->s_port);      else	port = DEFPORT;    }  /* Become a daemon. Take care to close inherited fds and to hold     first three one, lest master/slave ptys clash with standard     in,out,err   */  if (daemon (0, 0) < 0)    {      syslog (LOG_ERR, "failed to become a daemon %s", strerror (errno));      fatal (fileno (stderr), "fork failed, exiting", 0);    }  signal (SIGCHLD, rlogind_sigchld);  listenfd = socket (AF_INET, SOCK_STREAM, 0);  if (listenfd == -1)    {      syslog (LOG_ERR, "socket: %s", strerror (errno));      exit (1);    }  {    int on = 1;    setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);  }  size = sizeof saddr;  memset (&saddr, 0, size);  saddr.sin_family = AF_INET;  saddr.sin_addr.s_addr = htonl (INADDR_ANY);  saddr.sin_port = htons (port);  size = sizeof saddr;  if (bind (listenfd, (struct sockaddr *)&saddr, size) == -1)    {      syslog (LOG_ERR, "bind: %s", strerror (errno));      exit (1);    }  if (listen (listenfd, 128) == -1)    {      syslog (LOG_ERR, "listen: %s", strerror (errno));      exit (1);    }  while (1)    {      if (numchildren > maxchildren)        {	  syslog (LOG_ERR, "too many children (%d)", numchildren);          pause ();          continue;        }      size = sizeof saddr;      fd = accept (listenfd, (struct sockaddr *)&saddr, &size);      if (fd == -1)	{	  if (errno == EINTR)	    continue;	  syslog (LOG_ERR, "accept: %s", strerror (errno));	  exit (1);	}      pid = fork ();      if (pid == -1)	syslog (LOG_ERR, "fork: %s", strerror (errno));      else if (pid == 0) /* child */	{	  close (listenfd);	  exit (rlogind_mainloop (fd, fd));	}      else	numchildren++;      close (fd);    }}intrlogind_auth (int fd, struct auth_data *ap){  struct hostent *hp;  char *hostname;  int authenticated = 0;  confirmed = 0;  /* Check the remote host name */  hp = gethostbyaddr ((char *) &ap->from.sin_addr, sizeof (struct in_addr),		      ap->from.sin_family);  if (hp)    hostname = hp->h_name;  else if (reverse_required)    {      syslog (LOG_CRIT, "can't resolve remote IP address");      exit (1);    }  else    hostname = inet_ntoa (ap->from.sin_addr);  ap->hostname = strdup (hostname);  if (verify_hostname || in_local_domain (ap->hostname))    {      int match = 0;      for (hp = gethostbyname (ap->hostname); hp && !match; hp->h_addr_list++)	{	  if (hp->h_addr_list[0] == NULL)	    break;	  match = memcmp (hp->h_addr_list[0], &ap->from.sin_addr,			  sizeof (ap->from.sin_addr)) == 0;	}      if (!match)	{	  syslog (LOG_ERR | LOG_AUTH, "cannot find matching IP for %s (%s)",		  ap->hostname, inet_ntoa (ap->from.sin_addr));	  fatal (fd, "Permission denied", 0);	}    }#ifdef	KERBEROS  if (kerberos)    {      const char *err_msg;      int c = 0;      if (do_krb_login (fd, ap, &err_msg) == 0)	authenticated++;      else 	fatal (fd, err_msg, 0);      write (fd, &c, 1);      confirmed = 1;		/* we sent the null! */    }  else#endif    {      int port = ntohs(ap->from.sin_port);      if (ap->from.sin_family != AF_INET ||	  port >= IPPORT_RESERVED ||	  port < IPPORT_RESERVED / 2)	{	  syslog (LOG_NOTICE, "Connection from %s on illegal port %d",		  inet_ntoa (ap->from.sin_addr), port);	  fatal (fd, "Permission denied", 0);	}#ifdef IP_OPTIONS      {	u_char optbuf[BUFSIZ / 3], *cp;	char lbuf[BUFSIZ], *lp;	int optsize = sizeof (optbuf), ipproto;	struct protoent *ip;	if ((ip = getprotobyname ("ip")) != NULL)	  ipproto = ip->p_proto;	else	  ipproto = IPPROTO_IP;	if (getsockopt (0, ipproto, IP_OPTIONS, (char *) optbuf,			&optsize) == 0 && optsize != 0)	  {	    lp = lbuf;	    for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)	      sprintf (lp, " %2.2x", *cp);	    syslog (LOG_NOTICE,	      "Ignoring IP options: %s", lbuf);	    if (setsockopt (0, ipproto, IP_OPTIONS, (char *) NULL, optsize))	      {		syslog (LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");		exit (1);	      }	  }      }#endif /* IP_OPTIONS */      if (do_rlogin (fd, ap) == 0)	authenticated++;    }  if (confirmed == 0)    {      write (fd, "", 1);      confirmed = 1;		/* we sent the null! */    }  IF_ENCRYPT (des_write (fd, SECURE_MESSAGE, sizeof (SECURE_MESSAGE) - 1));  return authenticated;}voidsetup_tty (int fd, struct auth_data *ap){  register char *cp = strchr (ap->term + ENVSIZE, '/');  char *speed;  struct termios tt;  tcgetattr (fd, &tt);  if (cp)    {      *cp++ = '\0';      speed = cp;      cp = strchr (speed, '/');      if (cp)	*cp++ = '\0';#ifdef HAVE_CFSETSPEED      cfsetspeed (&tt, strtoul (speed, NULL, 10));#else      cfsetispeed (&tt, strtoul (speed, NULL, 10));      cfsetospeed (&tt, strtoul (speed, NULL, 10));#endif    }  tt.c_iflag = TTYDEF_IFLAG;  tt.c_oflag = TTYDEF_OFLAG;  tt.c_lflag = TTYDEF_LFLAG;  tcsetattr (fd, TCSAFLUSH, &tt);  ap->env[0] = ap->term;  ap->env[1] = 0;}#ifdef UTMPXchar *utmp_ptsid (); /*FIXME*/void utmp_init ();voidsetup_utmp (char *line){  char *ut_id = utmp_ptsid (line, "rl");  utmp_init (line + sizeof ("/dev/") - 1, ".rlogin", ut_id);}#else# define setup_utmp(line)#endifvoidexec_login(int authenticated, struct auth_data *ap){  if (authenticated)    {#ifdef SOLARIS      execle (path_login, "login", "-p",	      "-h", ap->hostname, ap->term, "-f", "--",	      ap->lusername, NULL, ap->env);#else      execle (path_login, "login", "-p",	      "-h", ap->hostname, "-f", 	      ap->lusername, NULL, ap->env);#endif    }  else    {#ifdef SOLARIS      execle (path_login, "login", "-p",	      "-h", ap->hostname, ap->term, "--",	      ap->lusername, NULL, ap->env);#else      execle (path_login, "login", "-p",	      "-h", ap->hostname, 	      ap->lusername, NULL, ap->env);#endif    }  syslog(LOG_ERR, "can't exec login: %m");}intrlogind_mainloop (int infd, int outfd){  size_t size;  struct auth_data auth_data;  int true;  char c;  int authenticated;  pid_t pid;  int master;  memset (&auth_data, 0, sizeof auth_data);  size = sizeof auth_data.from;  if (getpeername (infd, (struct sockaddr *) &auth_data.from, &size) < 0)    {      syslog (LOG_ERR, "Can't get peer name of remote host: %m");      fatal (outfd, "Can't get peer name of remote host", 1);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -