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

📄 rshd.c

📁 压缩包中包含LINUX下多个命令的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			     &local_addr, kdata, "", schedule,			     version);	  des_set_key (kdata->session, schedule);	}      else#endif	rc = krb_recvauth (authopts, 0, ticket, "rcmd",			   instance, &fromaddr,			   (struct sockaddr_in *) 0,			   kdata, "", (bit_64 *) 0, version);      if (rc != KSUCCESS)	{	  error ("Kerberos authentication failure: %s\n", krb_err_txt[rc]);	  exit (1);	}    }  else#endif    remuser = getstr ("remuser");  /* Read three strings from the client. */  locuser = getstr ("locuser");  cmdbuf = getstr ("command");  /* Look up locuser in the passerd file.  The locuser has\* to be a   * valid account on this system.   */  setpwent ();  pwd = getpwnam (locuser);  if (pwd == NULL)    {      syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: unknown login. cmd='%.80s'",	      remuser, hostname, locuser, cmdbuf);      if (errorstr == NULL)	errorstr = "Login incorrect.\n";      goto fail;    }  /* We'll execute the client's command in the home directory   * of locuser.   */  if (chdir (pwd->pw_dir) < 0)    {      (void) chdir ("/");      syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: no home directory. cmd='%.80s'",	      remuser, hostname, locuser, cmdbuf);      error ("No remote directory.\n");#ifdef notdef      exit (1);#endif    }#ifdef	KERBEROS  if (use_kerberos)    {      if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0')	{	  if (kuserok (kdata, locuser) != 0)	    {	      syslog (LOG_INFO|LOG_AUTH, "Kerberos rsh denied to %s.%s@%s",		      kdata->pname, kdata->pinst, kdata->prealm);	      error ("Permission denied.\n");	      exit (1);	    }	}    }  else#endif    if (errorstr || pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0'	&& (iruserok (fromp->sin_addr.s_addr, pwd->pw_uid == 0,		      remuser, locuser)) < 0)      {	if (__rcmd_errstr)	  syslog (LOG_INFO|LOG_AUTH,		  "%s@%s as %s: permission denied (%s). cmd='%.80s'",		  remuser, hostname, locuser, __rcmd_errstr, cmdbuf);	else	  syslog (LOG_INFO|LOG_AUTH,		  "%s@%s as %s: permission denied. cmd='%.80s'",		  remuser, hostname, locuser, cmdbuf);      fail:	if (errorstr == NULL)	  errorstr = "Permission denied.\n";	error (errorstr, errorhost);	exit (1);      }  /* If the locuser isn't root, then check if logins are disabled. */  if (pwd->pw_uid && !access (PATH_NOLOGIN, F_OK))    {      error ("Logins currently disabled.\n");      exit (1);    }  /* Now write the null byte back to the client telling it   * that everything is OK.   * Note that this means that any error message that we generate   * from now on (such as the perror() if the execl() fails), won't   * be seen by the rcomd() fucntion, but will be seen by the   * application that called rcmd() when it reads from the socket.   */  if (write (STDERR_FILENO, "\0", 1) < 0)    {      error ("Lost connection.\n");      exit (1);    }  sent_null = 1;  if (port)    {      /* We nee a secondary channel,  Here's where we create       * the control process that'll handle this secondary       * channel.       * First create a pipe to use for communication between       * the parent and child, then fork.       */      if (pipe (pv) < 0)	{	  error ("Can't make pipe.\n");	  exit (1);	}#ifdef ENCRYPTION#ifdef KERBEROS      if (doencrypt)	{	  if (pipe (pv1) < 0)	    {	      error ("Can't make 2nd pipe.\n");	      exit (1);	    }	  if (pipe (pv2) < 0)	    {	      error ("Can't make 3rd pipe.\n");	      exit (1);	    }	}#endif#endif      pid = fork ();      if (pid == -1)	{	  error ("Can't fork; try again.\n");	  exit (1);	}      if (pid)	{	  /* Parent process == control process.	   * We: (1) read from the pipe and write to s;	   *     (2) read from s and send corresponding	   *         signal.	   */#ifdef ENCRYPTION#ifdef KERBEROS	  if (doencrypt)	    {	      static char msg[] = SECURE_MESSAGE;	      close (pv1[1]);	      close (pv2[1]);	      des_write (s, msg, sizeof(msg) - 1);	    }	  else#endif#endif	    {	      /* child handles the original socket */	      close (STDIN_FILENO);	      /* (0, 1, and 2 were from inetd */	      close (STDOUT_FILENO);	    }	  close (STDERR_FILENO);	  close (pv[1]); /* close write end of pipe */	  FD_ZERO (&readfrom);	  FD_SET (s, &readfrom);	  FD_SET (pv[0], &readfrom);	  /* set max fd + 1 for select */	  if (pv[0] > s)	    nfd = pv[0];	  else	    nfd = s;#ifdef ENCRYPTION#ifdef KERBEROS	  if (doencrypt)	    {	      FD_ZERO (&writeto);	      FD_SET (pv2[0], &writeto);	      FD_SET (pv1[0], &readfrom);	      nfd = MAX (nfd, pv2[0]);	      nfd = MAX (nfd, pv1[0]);	    }	  else#endif#endif	    ioctl (pv[0], FIONBIO, (char *)&one);	  /* should set s nbio! */	  nfd++;	  do	    {	      ready = readfrom;#ifdef ENCRYPTION#ifdef KERBEROS	      if (doencrypt)		{		  wready = writeto;		  if (select (nfd, &ready, &wready, (fd_set *) 0,			      (struct timeval *) 0) < 0)		    break;		}	      else#endif#endif		if (select (nfd, &ready, (fd_set *)0,			    (fd_set *)0, (struct timeval *)0) < 0)		  /* wait until something to read */		  break;	      if (FD_ISSET (s, &ready))		{		  int	ret;#ifdef ENCRYPTION#ifdef KERBEROS		  if (doencrypt)		    ret = des_read (s, &sig, 1);		  else#endif#endif		    ret = read (s, &sig, 1);		  if (ret <= 0)		    FD_CLR (s, &readfrom);		  else		    killpg (pid, sig);		}	      if (FD_ISSET (pv[0], &ready))		{		  errno = 0;		  cc = read (pv[0], buf, sizeof buf);		  if (cc <= 0)		    {		      shutdown (s, 1+1);		      FD_CLR (pv[0], &readfrom);		    }		  else		    {#ifdef ENCRYPTION#ifdef KERBEROS		      if (doencrypt)			des_write (s, buf, cc);		      else#endif#endif			write (s, buf, cc);		    }		}#ifdef ENCRYPTION#ifdef KERBEROS	      if (doencrypt && FD_ISSET(pv1[0], &ready))		{		  errno = 0;		  cc = read (pv1[0], buf, sizeof(buf));		  if (cc <= 0)		    {		      shutdown (pv1[0], 1+1);		      FD_CLR (pv1[0], &readfrom);		    }		  else		    des_write (STDOUT_FILENO, buf, cc);		}	      if (doencrypt && FD_ISSET(pv2[0], &wready))		{		  errno = 0;		  cc = des_read (STDIN_FILENO, buf, sizeof buf);		  if (cc <= 0)		    {		      shutdown (pv2[0], 1+1);		      FD_CLR (pv2[0], &writeto);		    }		  else		    write (pv2[0], buf, cc);		}#endif#endif	    } while (FD_ISSET (s, &readfrom) ||#ifdef ENCRYPTION#ifdef KERBEROS		     (doencrypt && FD_ISSET (pv1[0], &readfrom)) ||#endif#endif		     FD_ISSET (pv[0], &readfrom));	  /* The pipe will generat an EOR whe the shell	   * terminates.  The socket will terninate whe the	   * client process terminates.	   */	  exit (0);	}      /* Child process. Become a process group leader, so that       * the control process above can send signals to all the       * processes we may be the parent of.  The process group ID       * (the getpid() value below) equals the childpid value from       * the fork above.       */      setpgid (0, getpid ());      close(s); /* control process handles this fd */      close (pv[0]); /* close read end of pipe */#ifdef ENCRYPTION#ifdef KERBEROS      if (doencrypt)	{	  close (pv1[0]); close (pv2[0]);	  dup2 (pv1[1], 1);	  dup2 (pv2[1], 0);	  close (pv1[1]);	  close (pv2[1]);	}#endif#endif      dup2 (pv[1], STDERR_FILENO); /* stderr of shell has to go				      pipe to control process */      close (pv[1]);    }  if (*pwd->pw_shell == '\0')    pwd->pw_shell = PATH_BSHELL;#if	BSD > 43  if (setlogin (pwd->pw_name) < 0)    syslog (LOG_ERR, "setlogin() failed: %m");#endif  /* Set the fid, then uid to become the user specified by "locuser" */  setegid ((gid_t)pwd->pw_gid);  setgid ((gid_t)pwd->pw_gid);#ifdef HAVE_INITGROUPS  initgroups (pwd->pw_name, pwd->pw_gid); /* BSD groups */#endif  seteuid ((uid_t)pwd->pw_uid);  setuid ((uid_t)pwd->pw_uid);  /* Set up an initial environment for the shell that we exec() */  environ = envinit;  strncat (homedir, pwd->pw_dir, sizeof(homedir)-6);  strcat (path, PATH_DEFPATH);  strncat (shell, pwd->pw_shell, sizeof(shell)-7);  strncat (username, pwd->pw_name, sizeof(username)-6);  cp = strrchr (pwd->pw_shell, '/');  if (cp)    cp++; /* step past first slash */  else    cp = pwd->pw_shell; /* no slash in shell string */  endpwent ();  if (log_success || pwd->pw_uid == 0)    {#ifdef	KERBEROS      if (use_kerberos)	syslog (LOG_INFO|LOG_AUTH,		"Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'",		kdata->pname, kdata->pinst, kdata->prealm,		hostname, locuser, cmdbuf);      else#endif	syslog (LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",		remuser, hostname, locuser, cmdbuf);    }  execl (pwd->pw_shell, cp, "-c", cmdbuf, 0);  perror (pwd->pw_shell);  exit (1);}/* * Report error to client.  Note: can't be used until second socket has * connected to client, or older clients will hang waiting for that * connection first. */void#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__error (const char *fmt, ...)#elseerror (fmt, va_alist)     char *fmt;     va_dcl#endif{  va_list ap;  int len;  char *bp, buf[BUFSIZ];#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__  va_start (ap, fmt);#else  va_start (ap);#endif  bp = buf;  if (sent_null == 0)    {      *bp++ = 1;      len = 1;    } else      len = 0;  vsnprintf (bp, sizeof(buf) - 1, fmt, ap);  write (STDERR_FILENO, buf, len + strlen (bp));}char *getstr(const char *err){  size_t buf_len = 100;  char *buf = malloc (buf_len), *end = buf;  if (! buf)    {      error ("Out of space reading %s\n", err);      exit (1);    }  do    {      /* Oh this is efficient, oh yes.  [But what can be done?] */      int rd = read (STDIN_FILENO, end, 1);      if (rd <= 0)	{	  if (rd == 0)	    error ("EOF reading %s\n", err);	  else	    perror (err);	  exit (1);	}      end += rd;      if ((buf + buf_len - end) < (buf_len >> 3))	{	  /* Not very much room left in our buffer, grow it. */	  size_t end_offs = end - buf;	  buf_len += buf_len;	  buf = realloc (buf, buf_len);	  if (! buf)	    {	      error ("Out of space reading %s\n", err);	      exit (1);	    }	  end = buf + end_offs;	}    } while (*(end - 1));  return buf;}/* * Check whether host h is in our local domain, * defined as sharing the last two components of the domain part, * or the entire domain part if the local domain has only one component. * If either name is unqualified (contains no '.'), * assume that the host is local, as it will be * interpreted as such. */intlocal_domain (const char *h){  extern char *localhost __P ((void));  char *hostname = localhost ();  if (! hostname)    return 0;  else    {      int is_local = 0;      const char *p1 = topdomain (hostname);      const char *p2 = topdomain (h);      if (p1 == NULL || p2 == NULL || !strcasecmp (p1, p2))	is_local = 1;      free (hostname);      return is_local;    }}const char *topdomain (const char *h){  const char *p, *maybe = NULL;  int dots = 0;  for (p = h + strlen(h); p >= h; p--)    {      if (*p == '.')	{	  if (++dots == 2)	    return p;	  maybe = p;	}    }  return maybe;}voidusage (){  syslog (LOG_ERR, "usage: rshd [-%s]", OPTIONS);  exit (2);}voidhelp (void){  puts ("usage: rshd [options]");  puts ("\   -a, --verify-hostname   Ask hostname for verification");  puts ("\   -l, --no-rhosts         Ignore .rhosts file");  puts ("\   -L, --log-session       Set local domain name");  puts ("\   -n, --no-keepalive      Do not set SO_KEEPALIVE");#ifdef KERBEROS  puts ("\   -k, --kerberos          Use kerberos IV authentication");#ifdef ENCRYPTION  puts ("\   -x, --encrypt           Use DES encryption");#endif /* ENCRYPTION */#endif /* KERBEROS */  puts ("\   -h, --help              Display usage instructions");  puts ("\   -V, --version           Display program version");  printf ("\nSend bug reports to %s\n", PACKAGE_BUGREPORT);}

⌨️ 快捷键说明

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