Exemple #1
0
int
__rmt_open (const char *path, int oflag, int bias, const char *remote_shell)
{
  int remote_pipe_number;	/* pseudo, biased file descriptor */
  char *path_copy;		/* copy of path string */
  char *cursor;			/* cursor in path_copy */
  char *remote_host;		/* remote host name */
  char *remote_file;		/* remote file name (often a device) */
  char *remote_user;		/* remote user name */
  char command_buffer[CMDBUFSIZE];

#ifndef HAVE_NETDB_H
  const char *remote_shell_basename;
  int status;
#endif

  /* Find an unused pair of file descriptors.  */

  for (remote_pipe_number = 0;
       remote_pipe_number < MAXUNIT;
       remote_pipe_number++)
    if (READ (remote_pipe_number) == -1
	&& WRITE (remote_pipe_number) == -1)
      break;

  if (remote_pipe_number == MAXUNIT)
    {
      errno = EMFILE;
      return -1;
    }

  /* Pull apart the system and device, and optional user.  */

  path_copy = xstrdup (path);
  remote_host = path_copy;
  remote_user = NULL;
  remote_file = NULL;

  for (cursor = path_copy; *cursor; cursor++)
    switch (*cursor)
      {
      default:
	break;

      case '@':
	if (!remote_user)
	  {
	    remote_user = remote_host;
	    *cursor = '\0';
	    remote_host = cursor + 1;
	  }
	break;

      case ':':
	if (!remote_file)
	  {
	    *cursor = '\0';
	    remote_file = cursor + 1;
	  }
	break;
      }

  /* FIXME: Should somewhat validate the decoding, here.  */

  if (*remote_user == '\0')
    remote_user = NULL;

#ifdef HAVE_NETDB_H

  /* Execute the remote command using rexec.  */

  READ (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
  if (READ (remote_pipe_number) < 0)
    {
      free (path_copy);
      return -1;
    }

  WRITE (remote_pipe_number) = READ (remote_pipe_number);

#else /* not HAVE_NETDB_H */

  /* Identify the remote command to be executed.  */

  if (!remote_shell)
    {
#ifdef REMOTE_SHELL
      remote_shell = REMOTE_SHELL;
#else
      errno = EIO;
      free (path_copy);
      return -1;
#endif
    }
  remote_shell_basename = strrchr (remote_shell, '/');
  if (remote_shell_basename)
    remote_shell_basename++;
  else
    remote_shell_basename = remote_shell;

  /* Set up the pipes for the `rsh' command, and fork.  */

  if (pipe (to_remote[remote_pipe_number]) == -1
      || pipe (from_remote[remote_pipe_number]) == -1)
    {
      free (path_copy);
      return -1;
    }

  status = fork ();
  if (status == -1)
    {
      free (path_copy);
      return -1;
    }

  if (status == 0)
    {

      /* Child.  */

      close (0);
      dup (to_remote[remote_pipe_number][0]);
      close (to_remote[remote_pipe_number][0]);
      close (to_remote[remote_pipe_number][1]);

      close (1);
      dup (from_remote[remote_pipe_number][1]);
      close (from_remote[remote_pipe_number][0]);
      close (from_remote[remote_pipe_number][1]);

      setuid (getuid ());
      setgid (getgid ());

      if (remote_user)
	execl (remote_shell, remote_shell_basename, remote_host,
	       "-l", remote_user, "/etc/rmt", (char *) 0);
      else
	execl (remote_shell, remote_shell_basename, remote_host,
	       "/etc/rmt", (char *) 0);

      /* Bad problems if we get here.  */
      
      /* In a previous version, _exit was used here instead of exit.  */
      error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
    }

  /* Parent.  */

  close (from_remote[remote_pipe_number][1]);
  close (to_remote[remote_pipe_number][0]);

#endif /* not HAVE_NETDB_H */

  /* Attempt to open the tape device.  */

  sprintf (command_buffer, "O%s\n%d\n", remote_file, oflag);
  if (do_command (remote_pipe_number, command_buffer) == -1
      || get_status (remote_pipe_number) == -1)
    {
      free (path_copy);
      return -1;
    }

  free (path_copy);
  return remote_pipe_number + bias;
}
/* Open a file (a magnetic tape device?) on the system specified in
   FILE_NAME, as the given user. FILE_NAME has the form `[USER@]HOST:FILE'.
   OPEN_MODE is O_RDONLY, O_WRONLY, etc.  If successful, return the
   remote pipe number plus BIAS.  REMOTE_SHELL may be overridden.  On
   error, return -1.  */
int
rmt_open__ (const char *file_name, int open_mode, int bias,
            const char *remote_shell)
{
  int remote_pipe_number;	/* pseudo, biased file descriptor */
  char *file_name_copy;		/* copy of file_name string */
  char *remote_host;		/* remote host name */
  char *remote_file;		/* remote file name (often a device) */
  char *remote_user;		/* remote user name */

  /* Find an unused pair of file descriptors.  */

  for (remote_pipe_number = 0;
       remote_pipe_number < MAXUNIT;
       remote_pipe_number++)
    if (READ_SIDE (remote_pipe_number) == -1
	&& WRITE_SIDE (remote_pipe_number) == -1)
      break;

  if (remote_pipe_number == MAXUNIT)
    {
      errno = EMFILE;
      return -1;
    }

  /* Pull apart the system and device, and optional user.  */

  {
    char *cursor;

    file_name_copy = xstrdup (file_name);
    remote_host = file_name_copy;
    remote_user = 0;
    remote_file = 0;

    for (cursor = file_name_copy; *cursor; cursor++)
      switch (*cursor)
	{
	default:
	  break;

	case '\n':
	  /* Do not allow newlines in the file_name, since the protocol
	     uses newline delimiters.  */
	  free (file_name_copy);
	  errno = ENOENT;
	  return -1;

	case '@':
	  if (!remote_user)
	    {
	      remote_user = remote_host;
	      *cursor = '\0';
	      remote_host = cursor + 1;
	    }
	  break;

	case ':':
	  if (!remote_file)
	    {
	      *cursor = '\0';
	      remote_file = cursor + 1;
	    }
	  break;
	}
  }

  /* FIXME: Should somewhat validate the decoding, here.  */
  if (gethostbyname (remote_host) == NULL)
    error (EXIT_ON_EXEC_ERROR, 0, _("Cannot connect to %s: resolve failed"),
	   remote_host);

  if (remote_user && *remote_user == '\0')
    remote_user = 0;

#if WITH_REXEC

  /* Execute the remote command using rexec.  */

  READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
  if (READ_SIDE (remote_pipe_number) < 0)
    {
      int e = errno;
      free (file_name_copy);
      errno = e;
      return -1;
    }

  WRITE_SIDE (remote_pipe_number) = READ_SIDE (remote_pipe_number);

#else /* not WITH_REXEC */
  {
    const char *remote_shell_basename;
    pid_t status;

    /* Identify the remote command to be executed.  */

    if (!remote_shell)
      {
#ifdef REMOTE_SHELL
	remote_shell = REMOTE_SHELL;
#else
	free (file_name_copy);
	errno = EIO;
	return -1;
#endif
      }
    remote_shell_basename = last_component (remote_shell);

    /* Set up the pipes for the `rsh' command, and fork.  */

    if (pipe (to_remote[remote_pipe_number]) == -1
	|| pipe (from_remote[remote_pipe_number]) == -1)
      {
	int e = errno;
	free (file_name_copy);
	errno = e;
	return -1;
      }

    status = fork ();
    if (status == -1)
      {
	int e = errno;
	free (file_name_copy);
	errno = e;
	return -1;
      }

    if (status == 0)
      {
	/* Child.  */

	if (dup2 (to_remote[remote_pipe_number][PREAD], STDIN_FILENO) < 0
	    || (to_remote[remote_pipe_number][PREAD] != STDIN_FILENO
		&& close (to_remote[remote_pipe_number][PREAD]) != 0)
	    || (to_remote[remote_pipe_number][PWRITE] != STDIN_FILENO
		&& close (to_remote[remote_pipe_number][PWRITE]) != 0)
	    || dup2 (from_remote[remote_pipe_number][PWRITE], STDOUT_FILENO) < 0
	    || close (from_remote[remote_pipe_number][PREAD]) != 0
	    || close (from_remote[remote_pipe_number][PWRITE]) != 0)
	  error (EXIT_ON_EXEC_ERROR, errno,
		 _("Cannot redirect files for remote shell"));

	sys_reset_uid_gid ();

	if (remote_user)
	  execl (remote_shell, remote_shell_basename, remote_host,
		 "-l", remote_user, rmt_command, (char *) 0);
	else
	  execl (remote_shell, remote_shell_basename, remote_host,
		 rmt_command, (char *) 0);

	/* Bad problems if we get here.  */

	/* In a previous version, _exit was used here instead of exit.  */
	error (EXIT_ON_EXEC_ERROR, errno, _("Cannot execute remote shell"));
      }

    /* Parent.  */

    close (from_remote[remote_pipe_number][PWRITE]);
    close (to_remote[remote_pipe_number][PREAD]);
  }
#endif /* not WITH_REXEC */

  /* Attempt to open the tape device.  */

  {
    size_t remote_file_len = strlen (remote_file);
    char *command_buffer = xmalloc (remote_file_len + 1000);
    sprintf (command_buffer, "O%s\n", remote_file);
    encode_oflag (command_buffer + remote_file_len + 2, open_mode);
    strcat (command_buffer, "\n");
    if (do_command (remote_pipe_number, command_buffer) == -1
	|| get_status (remote_pipe_number) == -1)
      {
	int e = errno;
	free (command_buffer);
	free (file_name_copy);
	_rmt_shutdown (remote_pipe_number, e);
	return -1;
      }
    free (command_buffer);
  }

  free (file_name_copy);
  return remote_pipe_number + bias;
}
Exemple #3
0
static int
/*ARGSUSED*/
_rmt_open(const char *path, int oflag, int mode)
{
	int i;
	char buffer[BUFMAGIC];
	char host[MAXHOSTLEN];
	char device[BUFMAGIC];
	char login[BUFMAGIC];
	char *sys, *dev, *user;
	const char *rshpath, *rsh;

	_DIAGASSERT(path != NULL);

	sys = host;
	dev = device;
	user = login;

/*
 *	first, find an open pair of file descriptors
 */

	for (i = 0; i < MAXUNIT; i++)
		if (READ(i) == -1 && WRITE(i) == -1)
			break;

	if (i == MAXUNIT) {
		errno = EMFILE;
		return -1;
	}

/*
 *	pull apart system and device, and optional user
 *	don't munge original string
 *	if COMPAT is defined, also handle old (4.2) style person.site notation.
 */

	while (*path != '@'
#ifdef COMPAT
			&& *path != '.'
#endif
			&& *path != ':') {
		*sys++ = *path++;
	}
	*sys = '\0';
	path++;

	if (*(path - 1) == '@') {
		(void)strncpy(user, host, sizeof(login) - 1);
				/* saw user part of user@host */
		sys = host;			/* start over */
		while (*path != ':') {
			*sys++ = *path++;
		}
		*sys = '\0';
		path++;
	}
#ifdef COMPAT
	else if (*(path - 1) == '.') {
		while (*path != ':') {
			*user++ = *path++;
		}
		*user = '******';
		path++;
	}
#endif
	else
		*user = '******';

	while (*path) {
		*dev++ = *path++;
	}
	*dev = '\0';

#ifdef USE_REXEC
/*
 *	Execute the remote command using rexec
 */
	READ(i) = WRITE(i) = _rmt_rexec(host, login);
	if (READ(i) < 0)
		return -1;
#else
/*
 *	setup the pipes for the 'rsh' command and fork
 */

	if (pipe(Ptc[i]) == -1 || pipe(Ctp[i]) == -1)
		return -1;

	switch (fork()) {
	case -1:
		return -1;

	case 0:
		close(0);
		dup(Ptc[i][0]);
		close(Ptc[i][0]); close(Ptc[i][1]);
		close(1);
		dup(Ctp[i][1]);
		close(Ctp[i][0]); close(Ctp[i][1]);
		(void) setuid(getuid());
		(void) setgid(getgid());

		if ((rshpath = getenv("RCMD_CMD")) == NULL)
			rshpath = _PATH_RSH;
		if ((rsh = strrchr(rshpath, '/')) == NULL)
			rsh = rshpath;
		else
			rsh++;

		if (*login) {
			execl(rshpath, rsh, host, "-l", login, _PATH_RMT, NULL);
		} else {
			execl(rshpath, rsh, host, _PATH_RMT, NULL);
		}

/*
 *	bad problems if we get here
 */

		err(1, "Cannnot exec %s", rshpath);
		/*FALLTHROUGH*/
	default:
		break;
	}

	close(Ptc[i][0]); close(Ctp[i][1]);
#endif

/*
 *	now attempt to open the tape device
 */

	(void)snprintf(buffer, sizeof(buffer), "O%s\n%d\n", device, oflag);
	if (command(i, buffer) == -1 || status(i) == -1)
		return -1;

	return i;
}