Browse code

Allow OpenVPN to run completely unprivileged under Linux by allowing openvpn --mktun to be used with --user and --group to set the UID/GID of the tun device node. Also added --iproute option to allow an alternative command to be executed in place of the default iproute2 command (Alon Bar-Lev).

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@2639 e7ae566f-a301-0410-adde-c780ea21d3b5

james authored on 2008/01/22 04:34:13
Showing 9 changed files
... ...
@@ -426,7 +426,7 @@ do_persist_tuntap (const struct options *options)
426 426
 	     "options --mktun or --rmtun should only be used together with --dev");
427 427
       tuncfg (options->dev, options->dev_type, options->dev_node,
428 428
 	      options->tun_ipv6, options->persist_mode,
429
-	      &options->tuntap_options);
429
+	      options->username, options->groupname, &options->tuntap_options);
430 430
       if (options->persist_mode && options->lladdr)
431 431
         set_lladdr(options->dev, options->lladdr, NULL);
432 432
       return true;
... ...
@@ -24,8 +24,8 @@ int set_lladdr(const char *ifname, const char *lladdr,
24 24
 #if defined(TARGET_LINUX)
25 25
 #ifdef CONFIG_FEATURE_IPROUTE
26 26
   openvpn_snprintf (cmd, sizeof (cmd),
27
-		    IPROUTE_PATH " link set addr %s dev %s",
28
-		    lladdr, ifname);
27
+		    "%s link set addr %s dev %s",
28
+		    iproute_path, lladdr, ifname);
29 29
 #else
30 30
   openvpn_snprintf (cmd, sizeof (cmd),
31 31
 		    IFCONFIG_PATH " %s hw ether %s",
... ...
@@ -44,6 +44,10 @@
44 44
 
45 45
 #include "memdbg.h"
46 46
 
47
+#ifdef CONFIG_FEATURE_IPROUTE
48
+const char *iproute_path = IPROUTE_PATH;
49
+#endif
50
+
47 51
 /* Redefine the top level directory of the filesystem
48 52
    to restrict access to files for security */
49 53
 void
... ...
@@ -269,4 +269,11 @@ void configure_path (void);
269 269
 void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
270 270
 #endif
271 271
 
272
+/*
273
+ * /sbin/ip path, may be overridden
274
+ */
275
+#ifdef CONFIG_FEATURE_IPROUTE
276
+extern const char *iproute_path;
277
+#endif
278
+
272 279
 #endif
... ...
@@ -71,6 +71,8 @@ openvpn \- secure IP tunnel daemon.
71 71
 [\ \fB\-\-dev\-type\fR\ \fIdevice\-type\fR\ ]
72 72
 [\ \fB\-\-dev\-node\fR\ \fInode\fR\ ]
73 73
 [\ \fB\-\-lladdr\fR\ \fIaddress\fR\ ]
74
+[\ \fB\-\-user\fR\ \fIuser\fR\ ]
75
+[\ \fB\-\-group\fR\ \fIgroup\fR\ ]
74 76
 .in -4
75 77
 .ti +4
76 78
 .hy
... ...
@@ -164,6 +166,7 @@ openvpn \- secure IP tunnel daemon.
164 164
 [\ \fB\-\-inetd\fR\ \fI[wait|nowait]\ [progname]\fR\ ]
165 165
 [\ \fB\-\-ip\-win32\fR\ \fImethod\fR\ ]
166 166
 [\ \fB\-\-ipchange\fR\ \fIcmd\fR\ ]
167
+[\ \fB\-\-iproute\fR\ \fIcmd\fR\ ]
167 168
 [\ \fB\-\-iroute\fR\ \fInetwork\ [netmask]\fR\ ]
168 169
 [\ \fB\-\-keepalive\fR\ \fIn\ m\fR\ ]
169 170
 [\ \fB\-\-key\-method\fR\ \fIm\fR\ ]
... ...
@@ -923,6 +926,11 @@ Specify the link layer address, more commonly known as the MAC address.
923 923
 Only applied to TAP devices.
924 924
 .\"*********************************************************
925 925
 .TP
926
+.B --iproute cmd
927
+Set alternate command to execute instead of default iproute2 command.
928
+May be used in order to execute OpenVPN in unprivileged environment.
929
+.\"*********************************************************
930
+.TP
926 931
 .B --ifconfig l rn
927 932
 Set TUN/TAP adapter parameters. 
928 933
 .B l
... ...
@@ -4306,6 +4314,14 @@ Remove a persistent tunnel.
4306 4306
 .B --dev tunX | tapX
4307 4307
 TUN/TAP device
4308 4308
 .\"*********************************************************
4309
+.TP
4310
+.B --user user
4311
+Optional user to be owner of this tunnel.
4312
+.\"*********************************************************
4313
+.TP
4314
+.B --group group
4315
+Optional group to be owner of this tunnel.
4316
+.\"*********************************************************
4309 4317
 .SS Windows-Specific Options:
4310 4318
 .\"*********************************************************
4311 4319
 .TP
... ...
@@ -156,6 +156,9 @@ static const char usage_message[] =
156 156
   "--lladdr hw     : Set the link layer address of the tap device.\n"
157 157
   "--topology t    : Set --dev tun topology: 'net30', 'p2p', or 'subnet'.\n"
158 158
   "--tun-ipv6      : Build tun link capable of forwarding IPv6 traffic.\n"
159
+#ifdef CONFIG_FEATURE_IPROUTE
160
+  "--iproute cmd   : Use this command instead of default " IPROUTE_PATH ".\n"
161
+#endif
159 162
   "--ifconfig l rn : TUN: configure device to use IP address l as a local\n"
160 163
   "                  endpoint and rn as a remote endpoint.  l & rn should be\n"
161 164
   "                  swapped on the other peer.  l & rn must be private\n"
... ...
@@ -591,6 +594,8 @@ static const char usage_message[] =
591 591
   "--rmtun         : Remove a persistent tunnel.\n"
592 592
   "--dev tunX|tapX : tun/tap device\n"
593 593
   "--dev-type dt   : Device type.  See tunnel options above for details.\n"
594
+  "--user user     : User to set privilege to.\n"
595
+  "--group group   : Group to set privilege to.\n"
594 596
 #endif
595 597
 #ifdef ENABLE_PKCS11
596 598
   "\n"
... ...
@@ -3225,6 +3230,13 @@ add_option (struct options *options,
3225 3225
       VERIFY_PERMISSION (OPT_P_UP);
3226 3226
       options->tun_ipv6 = true;
3227 3227
     }
3228
+#ifdef CONFIG_FEATURE_IPROUTE
3229
+  else if (streq (p[0], "iproute") && p[1])
3230
+    {
3231
+      VERIFY_PERMISSION (OPT_P_UP);
3232
+      iproute_path = p[1];
3233
+    }
3234
+#endif
3228 3235
   else if (streq (p[0], "ifconfig") && p[1] && p[2])
3229 3236
     {
3230 3237
       VERIFY_PERMISSION (OPT_P_UP);
... ...
@@ -777,7 +777,8 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
777 777
 
778 778
 #if defined(TARGET_LINUX)
779 779
 #ifdef CONFIG_FEATURE_IPROUTE
780
-  buf_printf (&buf, IPROUTE_PATH " route add %s/%d via %s",
780
+  buf_printf (&buf, "%s route add %s/%d via %s",
781
+  	      iproute_path,
781 782
 	      network,
782 783
 	      count_netmask_bits(netmask),
783 784
 	      gateway);
... ...
@@ -934,7 +935,8 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
934 934
 
935 935
 #if defined(TARGET_LINUX)
936 936
 #ifdef CONFIG_FEATURE_IPROUTE
937
-  buf_printf (&buf, IPROUTE_PATH " route del %s/%d",
937
+  buf_printf (&buf, "%s route del %s/%d",
938
+  	      iproute_path,
938 939
 	      network,
939 940
 	      count_netmask_bits(netmask));
940 941
 #else
... ...
@@ -577,7 +577,8 @@ do_ifconfig (struct tuntap *tt,
577 577
 	 * Set the MTU for the device
578 578
 	 */
579 579
 	openvpn_snprintf (command_line, sizeof (command_line),
580
-			  IPROUTE_PATH " link set dev %s up mtu %d",
580
+			  "%s link set dev %s up mtu %d",
581
+			  iproute_path,
581 582
 			  actual,
582 583
 			  tun_mtu
583 584
 			  );
... ...
@@ -590,7 +591,8 @@ do_ifconfig (struct tuntap *tt,
590 590
 		 * Set the address for the device
591 591
 		 */
592 592
 		openvpn_snprintf (command_line, sizeof (command_line),
593
-				  IPROUTE_PATH " addr add dev %s local %s peer %s",
593
+				  "%s addr add dev %s local %s peer %s",
594
+				  iproute_path,
594 595
 				  actual,
595 596
 				  ifconfig_local,
596 597
 				  ifconfig_remote_netmask
... ...
@@ -599,7 +601,8 @@ do_ifconfig (struct tuntap *tt,
599 599
 		  system_check (command_line, es, S_FATAL, "Linux ip addr add failed");
600 600
 	} else {
601 601
 		openvpn_snprintf (command_line, sizeof (command_line),
602
-				  IPROUTE_PATH " addr add dev %s %s/%d broadcast %s",
602
+				  "%s addr add dev %s %s/%d broadcast %s",
603
+				  iproute_path,
603 604
 				  actual,
604 605
 				  ifconfig_local,
605 606
 				  count_netmask_bits(ifconfig_remote_netmask),
... ...
@@ -1162,8 +1165,20 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
1162 1162
 
1163 1163
 #ifdef TUNSETPERSIST
1164 1164
 
1165
+/*
1166
+ * This can be removed in future
1167
+ * when all systems will use newer
1168
+ * linux-headers
1169
+ */
1170
+#ifndef TUNSETOWNER
1171
+#define TUNSETOWNER	_IOW('T', 204, int)
1172
+#endif
1173
+#ifndef TUNSETGROUP
1174
+#define TUNSETGROUP	_IOW('T', 206, int)
1175
+#endif
1176
+
1165 1177
 void
1166
-tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode, const struct tuntap_options *options)
1178
+tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
1167 1179
 {
1168 1180
   struct tuntap *tt;
1169 1181
 
... ...
@@ -1174,6 +1189,26 @@ tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6,
1174 1174
   open_tun (dev, dev_type, dev_node, ipv6, tt);
1175 1175
   if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)
1176 1176
     msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
1177
+  if (username != NULL)
1178
+    {
1179
+      struct user_state user_state;
1180
+
1181
+      if (!get_user (username, &user_state))
1182
+        msg (M_ERR, "Cannot get user entry for %s", username);
1183
+      else
1184
+        if (ioctl (tt->fd, TUNSETOWNER, user_state.pw->pw_uid) < 0)
1185
+          msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", username, dev);
1186
+    }
1187
+  if (groupname != NULL)
1188
+    {
1189
+      struct group_state group_state;
1190
+
1191
+      if (!get_group (groupname, &group_state))
1192
+        msg (M_ERR, "Cannot get group entry for %s", groupname);
1193
+      else
1194
+        if (ioctl (tt->fd, TUNSETGROUP, group_state.gr->gr_gid) < 0)
1195
+          msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", groupname, dev);
1196
+    }
1177 1197
   close_tun (tt);
1178 1198
   msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
1179 1199
 }
... ...
@@ -1185,6 +1220,19 @@ close_tun (struct tuntap *tt)
1185 1185
 {
1186 1186
   if (tt)
1187 1187
     {
1188
+#ifdef CONFIG_FEATURE_IPROUTE
1189
+	char command_line[256];
1190
+	/*
1191
+	 * Flush IP configuration for the device
1192
+	 */
1193
+	openvpn_snprintf (command_line, sizeof (command_line),
1194
+			  "%s addr flush dev %s",
1195
+			  iproute_path,
1196
+			  tt->actual_name
1197
+			  );
1198
+	msg (M_INFO, "%s", command_line);
1199
+	system_check (command_line, NULL, S_FATAL, "Linux ip flush failed");
1200
+#endif
1188 1201
       close_tun_generic (tt);
1189 1202
       free (tt);
1190 1203
     }
... ...
@@ -204,7 +204,8 @@ int write_tun (struct tuntap* tt, uint8_t *buf, int len);
204 204
 int read_tun (struct tuntap* tt, uint8_t *buf, int len);
205 205
 
206 206
 void tuncfg (const char *dev, const char *dev_type, const char *dev_node,
207
-	     bool ipv6, int persist_mode, const struct tuntap_options *options);
207
+	     bool ipv6, int persist_mode, const char *username,
208
+	     const char *groupname, const struct tuntap_options *options);
208 209
 
209 210
 const char *guess_tuntap_dev (const char *dev,
210 211
 			      const char *dev_type,