The attached patch is against openssh-4.3_p2 to allow non-root users to
vpn in over ssh. root access is still needed on client side (or an sudo
solution). Currently, I have it working with an sudo command to
configure a tap interface on the server side. eg to ssh into my gentoo
server:
# ssh -fw any:any user at ssh_server.box "sudo /etc/init.d/net.tap0
restart"
Then, configure the tap interface on the client side.
So far,
1.) the patch applies cleanly to 4.3_p2
2.) compiles cleanly on a Linux x86 system
3.) successfully permits non-root users to login, then access the tun
interface (via 'ioctl(fd, TUNSETOWNER, uid)')
To be done:
1.) propagate the change to the other platforms to clean up the
"#if defined(...)'s"
2.) verify no bugs have been introduced.
3.) verify I'm not smoking crack. :)
This is my first attempt at modifying openssh, so I'm sure I've screwed
up
a few conventions or security procedures. Let me know if I did and I'll
fix it.
thx,
Jason.
-------------- next part --------------
diff -Nurd openssh-4.3p2.orig/misc.c openssh-4.3p2/misc.c
--- openssh-4.3p2.orig/misc.c 2006-01-31 05:49:28.000000000 -0500
+++ openssh-4.3p2/misc.c 2006-08-25 09:01:31.000000000 -0400
@@ -579,12 +579,15 @@
return -1;
}
+#if defined(SSH_TUN_LINUX)
int
-tun_open(int tun, int mode)
+tun_open(int tun, int mode, uid_t uid)
{
-#if defined(CUSTOM_SYS_TUN_OPEN)
- return (sys_tun_open(tun, mode));
+ return (sys_tun_open(tun, mode, uid));
#elif defined(SSH_TUN_OPENBSD)
+int
+tun_open(int tun, int mode)
+{
struct ifreq ifr;
char name[100];
int fd = -1, sock;
diff -Nurd openssh-4.3p2.orig/misc.h openssh-4.3p2/misc.h
--- openssh-4.3p2.orig/misc.h 2006-01-31 05:49:28.000000000 -0500
+++ openssh-4.3p2/misc.h 2006-08-25 09:01:57.000000000 -0400
@@ -55,7 +55,11 @@
int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
-int tun_open(int, int);
+#if defined(SSH_TUN_LINUX)
+int tun_open(int, int, uid_t);
+#else
+int tun_open(int, int);
+#endif
/* Common definitions for ssh tunnel device forwarding */
#define SSH_TUNMODE_NO 0x00
diff -Nurd openssh-4.3p2.orig/openbsd-compat/port-tun.c
openssh-4.3p2/openbsd-compat/port-tun.c
--- openssh-4.3p2.orig/openbsd-compat/port-tun.c 2006-01-01 05:15:51.000000000
-0500
+++ openssh-4.3p2/openbsd-compat/port-tun.c 2006-08-25 09:02:36.000000000 -0400
@@ -39,7 +39,7 @@
#include <linux/if_tun.h>
int
-sys_tun_open(int tun, int mode)
+sys_tun_open(int tun, int mode, uid_t uid)
{
struct ifreq ifr;
int fd = -1;
@@ -77,6 +77,12 @@
goto failed;
}
+ if (ioctl(fd, TUNSETOWNER, uid) == -1) {
+ debug("%s: failed to set tunnel owner (uid %d): %s", __func__,
+ uid, strerror(errno));
+ goto failed;
+ }
+
if (tun == SSH_TUNID_ANY)
debug("%s: tunnel mode %d fd %d", __func__, mode, fd);
else
diff -Nurd openssh-4.3p2.orig/openbsd-compat/port-tun.h
openssh-4.3p2/openbsd-compat/port-tun.h
--- openssh-4.3p2.orig/openbsd-compat/port-tun.h 2006-01-01 03:47:06.000000000
-0500
+++ openssh-4.3p2/openbsd-compat/port-tun.h 2006-08-25 09:02:59.000000000 -0400
@@ -19,7 +19,10 @@
#include "channels.h"
-#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD)
+#if defined(SSH_TUN_LINUX)
+# define CUSTOM_SYS_TUN_OPEN
+int sys_tun_open(int, int, uid_t);
+#elif defined(SSH_TUN_FREEBSD)
# define CUSTOM_SYS_TUN_OPEN
int sys_tun_open(int, int);
#endif
diff -Nurd openssh-4.3p2.orig/serverloop.c openssh-4.3p2/serverloop.c
--- openssh-4.3p2.orig/serverloop.c 2005-12-31 00:33:37.000000000 -0500
+++ openssh-4.3p2/serverloop.c 2006-08-25 08:24:58.000000000 -0400
@@ -941,7 +941,11 @@
goto done;
tun = forced_tun_device;
}
- sock = tun_open(tun, mode);
+#if defined(SSH_TUN_LINUX)
+ sock = tun_open(tun, mode, the_authctxt->pw->pw_uid);
+#else
+ sock = tun_open(tun, mode);
+#endif
if (sock < 0)
goto done;
c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
diff -Nurd openssh-4.3p2.orig/ssh.c openssh-4.3p2/ssh.c
--- openssh-4.3p2.orig/ssh.c 2005-12-31 00:33:37.000000000 -0500
+++ openssh-4.3p2/ssh.c 2006-08-25 08:32:57.000000000 -0400
@@ -1073,8 +1073,13 @@
int fd;
debug("Requesting tun.");
+#if defined(SSH_TUN_LINUX)
+ if ((fd = tun_open(options.tun_local,
+ options.tun_open, original_real_uid)) >= 0) {
+#else
if ((fd = tun_open(options.tun_local,
options.tun_open)) >= 0) {
+#endif
c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "tun", 1);