A patch of mine which enables ssh to tunnel ppp traffic and run client
side "slaves" was recently sent to this list. DO NOT USE IT.

I wrote that tunneling patch around 7 months ago, when I was staying in
the country for a night and needed secure IP tunnel back home for the
evening from a single user machine.  It served that purpose amiably, but
install it on a multi-user box and you are dead in the water; anyone who
can run ssh -E can also run any command as root - which probably isn't
what you were looking for.

Included below is my current ssh tunneling/VPN patch. Use it instead.

example:

	ssh -C -e none -t -E "pppd -asycmap 0" gatekeeper.dec.com pppd passive

diff -u --recursive --exclude *.[oa] --minimal ssh-1.2.14.old/Makefile.in ssh-1.2.14/Makefile.in
--- ssh-1.2.14.old/Makefile.in	Thu Jun  6 23:47:08 1996
+++ ssh-1.2.14/Makefile.in	Tue Jul 30 01:11:20 1996
@@ -163,7 +163,7 @@
 	log-server.o login.o hostfile.o canohost.o servconf.o tildexpand.o \
 	serverloop.o $(COMMON_OBJS)
 SSH_OBJS = ssh.o sshconnect.o log-client.o readconf.o hostfile.o readpass.o \
-	tildexpand.o clientloop.o canohost.o $(COMMON_OBJS)
+	tildexpand.o clientloop.o canohost.o pty.o $(COMMON_OBJS)
 KEYGEN_OBJS = ssh-keygen.o log-client.o readpass.o rsa.o randoms.o md5.o \
 	buffer.o xmalloc.o authfile.o tss.o cipher.o des.o arcfour.o mpaux.o \
 	bufaux.o userfile.o signals.o $(LIBOBJS) $(CONFOBJS)
diff -u --recursive --exclude *.[oa] --minimal ssh-1.2.14.old/clientloop.c ssh-1.2.14/clientloop.c
--- ssh-1.2.14.old/clientloop.c	Thu Jun  6 23:47:05 1996
+++ ssh-1.2.14/clientloop.c	Tue Jul 30 05:57:59 1996
@@ -49,6 +49,11 @@
    in a configuration file. */
 extern char *host;
 
+#ifndef NOPROFF
+/* flag to quit client loop, and disconnect */
+  int quit_pending;
+#endif
+
 #ifdef SIGWINCH
 /* Flag to indicate that we have received a window change signal which has
    not yet been processed.  This will cause a message indicating the new
@@ -85,7 +90,9 @@
 static int connection_in; /* Connection to server (input). */
 static int connection_out; /* Connection to server (output). */
 static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
+#ifdef NOPROFF
 static int quit_pending; /* Set to non-zero to quit the client loop. */
+#endif
 static int escape_char; /* Escape character. */
 
 /* Returns the user\'s terminal to normal mode if it had been put in raw 
--- ssh-1.2.14/ssh.c~	Tue Jul 30 09:50:46 1996
+++ ssh-1.2.14/ssh.c	Sun Aug  4 11:17:41 1996
@@ -94,6 +94,9 @@
 #include "authfd.h"
 #include "readconf.h"
 #include "userfile.h"
+#ifndef NOPROFF
+#  include "pty.h"
+#endif
 
 /* Random number generator state.  This is initialized in ssh_login, and
    left initialized.  This is used both by the packet module and by various
@@ -116,6 +119,13 @@
    on the command line. */
 int stdin_null_flag = 0;
 
+#ifndef NOPROFF
+/* Flag indicating that when the client is running a slave stderr should
+   be redirected to the remote host, rather than the users stderr.
+   This can be set on the command line. */
+int redirect_stderr_flag = 0;
+#endif
+
 /* Flag indicating that ssh should fork after authentication.  This is useful
    so that the pasphrase can be entered manually, and then ssh goes to the
    background. */
@@ -147,7 +157,6 @@
 /* Host private key. */
 RSAPrivateKey host_private_key;
 
-
 /* Prints a help message to the user.  This function never returns. */
 
 void usage()
@@ -164,6 +173,10 @@
   fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
   fprintf(stderr, "  -f          Fork into background after authentication.\n");
   fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
+#ifndef NOPROFF
+  fprintf(stderr, "  -E cmd      Execute slave command under client, with stdin/out redirected.\n");
+  fprintf(stderr, "  -r          When running a slave, redirect stderr too.\n");
+#endif
   fprintf(stderr, "  -c cipher   Select encryption algorithm: ``idea'' (default, secure),\n");
   fprintf(stderr, "              ``des'', ``3des'', ``tss'', ``arcfour'' (fast, suitable for bulk\n");
   fprintf(stderr, "              transfers), ``none'' (no encryption - for debugging only).\n");
@@ -246,16 +259,26 @@
 #endif /* RSH_PATH */
 }
 
-/* Main program for the ssh client. */
+#ifndef NOPROFF
+extern int quit_pending;
+RETSIGTYPE sigchld_reaper(int sig)
+{
+  debug("Client received SIGCHILD from slave");
+  quit_pending = 1;
+}
+#endif
 
+/* Main program for the ssh client. */
 int main(int ac, char **av)
 {
   int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port, authfd;
+
   char *optarg, *cp, buf[256];
   Buffer command;
   struct stat st;
   struct passwd *pw, pwcopy;
   int interactive = 0, dummy;
+  char *execute=NULL;
   uid_t original_real_uid;
   uid_t original_effective_uid;
 #ifdef SIGWINCH
@@ -330,7 +353,11 @@
       opt = av[optind][1];
       if (!opt)
 	usage();
+#ifndef NOPROFF
+      if (strchr("EeilcpLRo", opt)) /* options with arguments */
+#else
       if (strchr("eilcpLRo", opt)) /* options with arguments */
+#endif
 	{
 	  optarg = av[optind] + 2;
 	  if (strcmp(optarg, "") == 0)
@@ -351,7 +378,14 @@
 	case 'n':
 	  stdin_null_flag = 1;
 	  break;
-
+#ifndef NOPROFF
+       case 'E':
+         execute = optarg;
+         break;
+       case 'r':
+	 redirect_stderr_flag = 1;
+	 break;
+#endif
 	case 'f':
 	  fork_after_authentication_flag = 1;
 	  stdin_null_flag = 1;
@@ -498,7 +532,10 @@
   if (optind == ac)
     {
       /* No command specified - execute shell on a tty. */
-      tty_flag = 1;
+#ifndef NOPROFF
+      if (!execute)
+#endif
+	      tty_flag = 1;
     }
   else
     {
@@ -516,11 +553,19 @@
     fatal("Cannot fork into background without a command to execute.");
   
   /* Allocate a tty by default if no command specified. */
+#ifndef NOPROFF
+  if (!execute && buffer_len(&command) == 0)
+#else
   if (buffer_len(&command) == 0)
+#endif
     tty_flag = 1;
 
   /* Do not allocate a tty if stdin is not a tty. */
+#ifndef NOPROFF
+  if (!execute && !isatty(fileno(stdin)))
+#else
   if (!isatty(fileno(stdin)))
+#endif
     {
       if (tty_flag)
 	fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
@@ -845,7 +890,135 @@
     }
 
   /* Enter the interactive session. */
+#ifndef NOPROFF
+  if (execute)
+    {
+      /* name of slave pty */
+      char ttydev[128] = "";
+
+      signal (SIGCHLD, sigchld_reaper);
+      if (tty_flag)
+	{
+	  /* things like slip/ppp need a tty dicipline in the kernel to
+	     attach themselves to, so, we create a tty for the slave
+	     in order to allow such dependent protocols to tunnel over
+	     ssh connections - Julian Assange (proff@suburbia.net) */
+
+	  pid_t child;
+	  int ptyfd, ttyfd;
+	  if (!pty_allocate (&ptyfd, &ttyfd, ttydev))
+	    exit (1);
+	  debug ("Client slave tty = %.127s", ttydev);
+	  /* Change ownership of the tty. */
+	  debug ("Setting tty ownership to uid %d", original_real_uid);
+	  chown (ttydev, original_real_uid, -1);	/* gid not important with these perms */
+	  chmod (ttydev, 0600);
+
+	  if ((child = fork ()) == 0)
+	    {
+#ifdef USING_TERMIOS
+	      struct termios tio;
+#endif
+#ifdef USING_SGTTY
+	      struct sgttyb tio;
+#endif
+	      int init_tty;
+	      signal (SIGCHLD, SIG_DFL);
+#ifdef HAVE_SETSID
+	      if (setsid () < 0)
+		error ("setsid: %.100s", strerror (errno));
+#endif /* HAVE_SETSID */
+	      close (ptyfd);
+	      pty_make_controlling_tty (&ttyfd, ttydev);
+	      /* if we were invoked from a tty, we steal our
+	         initial settings from there */
+	      init_tty = isatty (fileno (stdin)) ? fileno (stdin) : ttyfd;
+#ifdef USING_TERMIOS
+	      tcgetattr (init_tty, &tio);
+#endif
+#ifdef USING_SGTTY
+	      ioctl (init_tty, TIOCGETP, &tio);
+#endif
+	      /* bad things happen if we have echo
+	         enabled at both ends of the tunnel ;) */
+#ifdef USING_TERMIOS
+	      tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+	      tcsetattr (ttyfd, TCSANOW, &tio);
+#endif
+#ifdef USING_SGTTY
+	      tio.sg_flags &= ~(ECHO);
+	      ioctl (ttyfd, TIOCSETP, &tio);
+#endif
+	      debug ("(pid %d) running sh -c \"%.500s\"", getpid (), execute);
+	      /* take over stdin/out */
+	      if (ttyfd != 0)
+		{
+		  dup2 (ttyfd, 0);
+		  close (ttyfd);
+		}
+	      dup2 (0, 1);
+	      if (redirect_stderr_flag)
+		dup2 (1, 2);
+	      setuid (original_real_uid);
+	      execl ("/bin/sh", "ssh-slave", "-c", execute);
+	      perror ("sh");
+	      _exit (1);
+	    }
+	  if (child == -1)
+	    {
+	      perror ("fork");
+	      exit (1);
+	    }
+	  close (ttyfd);
+	  if (ptyfd != 0)
+	    {
+	      dup2 (ptyfd, 0);
+	      close (ptyfd);
+	    }
+	  dup2 (0, 1);
+	  if (redirect_stderr_flag)
+	    dup2 (1, 2);
+	}
+      else
+	{
+	  /* simpler case, just use a pipe */
+
+	  int p1[2], p2[2];
+	  pid_t child;
+	  pipe (p1);
+	  pipe (p2);
+	  if ((child = fork ()) == 0)
+	    {
+	      signal (SIGCHLD, SIG_DFL);
+	      close (p1[1]);
+	      close (p2[0]);
+	      dup2 (p1[0], 0);
+	      dup2 (p2[1], 1);
+	      if (redirect_stderr_flag)
+		dup2 (1, 2);
+	      setuid (original_real_uid);
+	      execl ("/bin/sh", "ssh-slave", "-c", execute);
+	      perror ("sh");
+	      _exit (1);
+	    }
+	  if (child == -1)
+	    {
+	      perror ("fork");
+	      exit (1);
+	    }
+	  close (p1[0]);
+	  close (p2[1]);
+	  dup2 (p2[0], 0);
+	  dup2 (p1[1], 1);
+	}
+      exit_status = client_loop (tty_flag, tty_flag ? options.escape_char : -1);
+      if (tty_flag)
+	pty_release (ttydev);
+} else
+  exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
+#else
   exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
+#endif
 
   /* Close the connection to the remote host. */
   packet_close();
