Browse code

Management interface can now listen on a unix domain socket, for example:

management /tmp/openvpn unix

Also added management-client-user and management-client-group
directives to control which processes are allowed to connect
to the socket.


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

james authored on 2008/09/30 15:11:38
Showing 16 changed files
... ...
@@ -26,9 +26,17 @@
26 26
 #define BASIC_H
27 27
 
28 28
 /* bool definitions */
29
+#ifndef bool
29 30
 #define bool int
31
+#endif
32
+
33
+#ifndef true
30 34
 #define true 1
35
+#endif
36
+
37
+#ifndef false
31 38
 #define false 0
39
+#endif
32 40
 
33 41
 #define BOOL_CAST(x) ((x) ? (true) : (false))
34 42
 
... ...
@@ -339,7 +339,7 @@ AC_CHECK_HEADERS(fcntl.h stdlib.h dnl
339 339
 
340 340
 if test "${WIN32}" != "yes"; then
341 341
    AC_HEADER_SYS_WAIT
342
-   AC_CHECK_HEADERS(sys/time.h sys/socket.h sys/ioctl.h sys/stat.h dnl
342
+   AC_CHECK_HEADERS(sys/time.h sys/socket.h sys/un.h sys/ioctl.h sys/stat.h dnl
343 343
 		 sys/mman.h fcntl.h sys/file.h stdlib.h stdint.h dnl
344 344
 		 stdarg.h unistd.h signal.h stdio.h string.h dnl
345 345
 		 strings.h ctype.h errno.h syslog.h pwd.h grp.h dnl
... ...
@@ -464,7 +464,7 @@ AC_CHECK_FUNCS(daemon chroot getpwnam setuid nice system getpid dup dup2 dnl
464 464
 	       getpass strerror syslog openlog mlockall getgrnam setgid dnl
465 465
 	       setgroups stat flock readv writev time dnl
466 466
 	       setsid chdir putenv getpeername unlink dnl
467
-	       chsize ftruncate execve)
467
+	       chsize ftruncate execve getpeereid umask)
468 468
 
469 469
 # Windows use stdcall for winsock so we cannot auto detect these
470 470
 m4_define([SOCKET_FUNCS], [socket recv recvfrom send sendto listen dnl
... ...
@@ -64,6 +64,32 @@
64 64
    obj:/lib/ld-2.5.so
65 65
    obj:/lib/ld-2.5.so
66 66
    obj:/lib/ld-2.5.so
67
+   obj:/lib/ld-2.5.so
68
+   obj:/lib/ld-2.5.so
69
+   obj:/lib/ld-2.5.so
70
+   obj:/lib/libc-2.5.so
71
+   obj:/lib/ld-2.5.so
72
+   fun:__libc_dlopen_mode
73
+   fun:__nss_lookup_function
74
+   obj:/lib/libc-2.5.so
75
+   fun:getpwnam_r
76
+   fun:getpwnam
77
+   fun:get_user
78
+   fun:management_open
79
+   fun:open_management
80
+   fun:main
81
+}
82
+
83
+{
84
+   <insert a suppression name here>
85
+   Memcheck:Addr8
86
+   obj:/lib/ld-2.5.so
87
+   obj:/lib/ld-2.5.so
88
+   obj:/lib/ld-2.5.so
89
+   obj:/lib/ld-2.5.so
90
+   obj:/lib/ld-2.5.so
91
+   obj:/lib/ld-2.5.so
92
+   obj:/lib/ld-2.5.so
67 93
    obj:/lib/libc-2.5.so
68 94
    obj:/lib/ld-2.5.so
69 95
    fun:__libc_dlopen_mode
... ...
@@ -177,6 +203,79 @@
177 177
 
178 178
 {
179 179
    <insert a suppression name here>
180
+   Memcheck:Addr8
181
+   obj:/lib/ld-2.7.so
182
+   obj:/lib/ld-2.7.so
183
+   obj:/lib/ld-2.7.so
184
+   obj:/lib/ld-2.7.so
185
+   obj:/lib/ld-2.7.so
186
+   obj:/lib/ld-2.7.so
187
+   obj:/lib/ld-2.7.so
188
+   obj:/lib/ld-2.7.so
189
+   obj:/lib/ld-2.7.so
190
+   obj:/lib/ld-2.7.so
191
+   obj:/lib/libc-2.7.so
192
+   obj:/lib/ld-2.7.so
193
+   fun:__libc_dlopen_mode
194
+   fun:__nss_lookup_function
195
+   obj:/lib/libc-2.7.so
196
+   fun:getpwnam_r
197
+   fun:getpwnam
198
+   fun:get_user
199
+   fun:management_open
200
+   fun:open_management
201
+   fun:main
202
+}
203
+
204
+{
205
+   <insert a suppression name here>
206
+   Memcheck:Cond
207
+   fun:BN_div
208
+   fun:BN_MONT_CTX_set
209
+   fun:BN_MONT_CTX_set_locked
210
+   obj:/usr/lib/libcrypto.so.0.9.8
211
+   fun:ssl3_ctx_ctrl
212
+   fun:init_ssl
213
+   fun:init_instance
214
+   fun:init_instance_handle_signals
215
+   fun:tunnel_server_udp
216
+   fun:main
217
+}
218
+
219
+{
220
+   <insert a suppression name here>
221
+   Memcheck:Cond
222
+   fun:BN_div
223
+   fun:BN_nnmod
224
+   fun:BN_mod_inverse
225
+   fun:BN_MONT_CTX_set
226
+   fun:BN_MONT_CTX_set_locked
227
+   obj:/usr/lib/libcrypto.so.0.9.8
228
+   fun:ssl3_ctx_ctrl
229
+   fun:init_ssl
230
+   fun:init_instance
231
+   fun:init_instance_handle_signals
232
+   fun:tunnel_server_udp
233
+   fun:main
234
+}
235
+
236
+{
237
+   <insert a suppression name here>
238
+   Memcheck:Cond
239
+   fun:BN_mod_inverse
240
+   fun:BN_MONT_CTX_set
241
+   fun:BN_MONT_CTX_set_locked
242
+   obj:/usr/lib/libcrypto.so.0.9.8
243
+   fun:ssl3_ctx_ctrl
244
+   fun:init_ssl
245
+   fun:init_instance
246
+   fun:init_instance_handle_signals
247
+   fun:tunnel_server_udp
248
+   fun:main
249
+}
250
+
251
+{
252
+   <insert a suppression name here>
180 253
    Memcheck:Cond
181 254
    obj:/lib/ld-2.5.so
182 255
    obj:/lib/ld-2.5.so
... ...
@@ -428,6 +527,26 @@
428 428
    obj:/lib/ld-2.5.so
429 429
    obj:/lib/ld-2.5.so
430 430
    obj:/lib/libc-2.5.so
431
+   obj:/lib/ld-2.5.so
432
+   fun:__libc_dlopen_mode
433
+   fun:__nss_lookup_function
434
+   obj:/lib/libc-2.5.so
435
+   fun:getpwnam_r
436
+   fun:getpwnam
437
+   fun:get_user
438
+   fun:management_open
439
+   fun:open_management
440
+   fun:main
441
+}
442
+
443
+{
444
+   <insert a suppression name here>
445
+   Memcheck:Cond
446
+   obj:/lib/ld-2.5.so
447
+   obj:/lib/ld-2.5.so
448
+   obj:/lib/ld-2.5.so
449
+   obj:/lib/ld-2.5.so
450
+   obj:/lib/libc-2.5.so
431 451
    obj:/lib/libdl-2.5.so
432 452
    obj:/lib/ld-2.5.so
433 453
    obj:/lib/libdl-2.5.so
... ...
@@ -522,6 +641,21 @@
522 522
    <insert a suppression name here>
523 523
    Memcheck:Leak
524 524
    fun:malloc
525
+   fun:__nss_lookup_function
526
+   obj:*
527
+   obj:*
528
+   fun:getpwnam_r
529
+   fun:getpwnam
530
+   fun:get_user
531
+   fun:management_open
532
+   fun:open_management
533
+   fun:main
534
+}
535
+
536
+{
537
+   <insert a suppression name here>
538
+   Memcheck:Leak
539
+   fun:malloc
525 540
    fun:getdelim
526 541
    fun:getpass
527 542
    fun:get_console_input
... ...
@@ -587,6 +721,22 @@
587 587
    <insert a suppression name here>
588 588
    Memcheck:Leak
589 589
    fun:malloc
590
+   fun:tsearch
591
+   fun:__nss_lookup_function
592
+   obj:*
593
+   obj:*
594
+   fun:getpwnam_r
595
+   fun:getpwnam
596
+   fun:get_user
597
+   fun:management_open
598
+   fun:open_management
599
+   fun:main
600
+}
601
+
602
+{
603
+   <insert a suppression name here>
604
+   Memcheck:Leak
605
+   fun:malloc
590 606
    obj:/lib/libc-2.5.so
591 607
    fun:__nss_database_lookup
592 608
    obj:*
... ...
@@ -636,3 +786,122 @@
636 636
    fun:main
637 637
 }
638 638
 
639
+{
640
+   <insert a suppression name here>
641
+   Memcheck:Leak
642
+   fun:malloc
643
+   obj:/lib/libc-2.5.so
644
+   fun:__nss_database_lookup
645
+   obj:*
646
+   obj:*
647
+   fun:getpwnam_r
648
+   fun:getpwnam
649
+   fun:get_user
650
+   fun:management_open
651
+   fun:open_management
652
+   fun:main
653
+}
654
+
655
+{
656
+   <insert a suppression name here>
657
+   Memcheck:Leak
658
+   fun:malloc
659
+   obj:/lib/libc-2.7.so
660
+   fun:__nss_database_lookup
661
+   obj:*
662
+   obj:*
663
+   fun:getpwnam_r
664
+   fun:getpwnam
665
+   fun:get_user
666
+   fun:management_open
667
+   fun:open_management
668
+   fun:main
669
+}
670
+
671
+{
672
+   <insert a suppression name here>
673
+   Memcheck:Addr8
674
+   obj:/lib/ld-2.7.so
675
+   obj:/lib/ld-2.7.so
676
+   obj:/lib/ld-2.7.so
677
+   obj:/lib/ld-2.7.so
678
+   obj:/lib/ld-2.7.so
679
+   obj:/lib/ld-2.7.so
680
+   obj:/lib/ld-2.7.so
681
+   obj:/lib/ld-2.7.so
682
+   obj:/lib/ld-2.7.so
683
+   obj:/lib/ld-2.7.so
684
+   obj:/lib/libc-2.7.so
685
+   obj:/lib/ld-2.7.so
686
+   fun:__libc_dlopen_mode
687
+   fun:__nss_lookup_function
688
+   obj:/lib/libc-2.7.so
689
+   fun:getgrnam_r
690
+   fun:getgrnam
691
+   fun:get_group
692
+   fun:do_init_first_time
693
+   fun:init_instance
694
+   fun:init_instance_handle_signals
695
+   fun:tunnel_server_udp
696
+   fun:main
697
+}
698
+
699
+{
700
+   <insert a suppression name here>
701
+   Memcheck:Leak
702
+   fun:malloc
703
+   obj:/lib/libc-2.7.so
704
+   fun:__nss_database_lookup
705
+   obj:*
706
+   obj:*
707
+   fun:getgrnam_r
708
+   fun:getgrnam
709
+   fun:get_group
710
+   fun:do_init_first_time
711
+   fun:init_instance
712
+   fun:init_instance_handle_signals
713
+   fun:tunnel_server_udp
714
+   fun:main
715
+}
716
+
717
+{
718
+   <insert a suppression name here>
719
+   Memcheck:Addr8
720
+   obj:/lib/ld-2.7.so
721
+   obj:/lib/ld-2.7.so
722
+   obj:/lib/ld-2.7.so
723
+   obj:/lib/ld-2.7.so
724
+   obj:/lib/ld-2.7.so
725
+   obj:/lib/ld-2.7.so
726
+   obj:/lib/ld-2.7.so
727
+   obj:/lib/ld-2.7.so
728
+   obj:/lib/ld-2.7.so
729
+   obj:/lib/ld-2.7.so
730
+   obj:/lib/libc-2.7.so
731
+   obj:/lib/ld-2.7.so
732
+   fun:__libc_dlopen_mode
733
+   fun:__nss_lookup_function
734
+   obj:/lib/libc-2.7.so
735
+   fun:getgrnam_r
736
+   fun:getgrnam
737
+   fun:get_group
738
+   fun:management_open
739
+   fun:open_management
740
+   fun:main
741
+}
742
+
743
+{
744
+   <insert a suppression name here>
745
+   Memcheck:Leak
746
+   fun:malloc
747
+   fun:tsearch
748
+   fun:__nss_lookup_function
749
+   obj:*
750
+   obj:*
751
+   fun:getgrnam_r
752
+   fun:getgrnam
753
+   fun:get_group
754
+   fun:management_open
755
+   fun:open_management
756
+   fun:main
757
+}
... ...
@@ -1290,11 +1290,11 @@ io_wait_dowork (struct context *c, const unsigned int flags)
1290 1290
   struct event_set_return esr[4];
1291 1291
 
1292 1292
   /* These shifts all depend on EVENT_READ and EVENT_WRITE */
1293
-  static const int socket_shift = 0;     /* depends on SOCKET_READ and SOCKET_WRITE */
1294
-  static const int tun_shift = 2;        /* depends on TUN_READ and TUN_WRITE */
1295
-  static const int err_shift = 4;        /* depends on ES_ERROR */
1293
+  static int socket_shift = 0;     /* depends on SOCKET_READ and SOCKET_WRITE */
1294
+  static int tun_shift = 2;        /* depends on TUN_READ and TUN_WRITE */
1295
+  static int err_shift = 4;        /* depends on ES_ERROR */
1296 1296
 #ifdef ENABLE_MANAGEMENT
1297
-  static const int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */
1297
+  static int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */
1298 1298
 #endif
1299 1299
 
1300 1300
   /*
... ...
@@ -2670,6 +2670,8 @@ open_management (struct context *c)
2670 2670
 			       c->options.management_addr,
2671 2671
 			       c->options.management_port,
2672 2672
 			       c->options.management_user_pass,
2673
+			       c->options.management_client_user,
2674
+			       c->options.management_client_group,
2673 2675
 			       c->options.management_log_history_cache,
2674 2676
 			       c->options.management_echo_buffer_size,
2675 2677
 			       c->options.management_state_buffer_size,
... ...
@@ -226,6 +226,15 @@ man_prompt (struct management *man)
226 226
 }
227 227
 
228 228
 static void
229
+man_delete_unix_socket (struct management *man)
230
+{
231
+#if UNIX_SOCK_SUPPORT
232
+  if (man->settings.flags & MF_LISTEN_UNIX)
233
+    socket_delete_unix (&man->settings.local_unix);
234
+#endif
235
+}
236
+
237
+static void
229 238
 man_close_socket (struct management *man, const socket_descriptor_t sd)
230 239
 {
231 240
 #ifndef WIN32
... ...
@@ -1231,9 +1240,18 @@ man_new_connection_post (struct management *man, const char *description)
1231 1231
   man_start_ne32 (man);
1232 1232
 #endif
1233 1233
 
1234
-  msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
1235
-       description,
1236
-       print_sockaddr (&man->settings.local, &gc));
1234
+#if UNIX_SOCK_SUPPORT
1235
+  if (man->settings.flags & MF_LISTEN_UNIX)
1236
+    {
1237
+      msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
1238
+	   description,
1239
+	   sockaddr_unix_name (&man->settings.local_unix, "NULL"));
1240
+    }
1241
+  else
1242
+#endif
1243
+    msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
1244
+	 description,
1245
+	 print_sockaddr (&man->settings.local, &gc));
1237 1246
 
1238 1247
   buffer_list_reset (man->connection.out);
1239 1248
 
... ...
@@ -1249,11 +1267,46 @@ static void
1249 1249
 man_accept (struct management *man)
1250 1250
 {
1251 1251
   struct link_socket_actual act;
1252
+  CLEAR (act);
1252 1253
 
1253 1254
   /*
1254
-   * Accept the TCP client.
1255
+   * Accept the TCP or Unix domain socket client.
1255 1256
    */
1256
-  man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &act, false);
1257
+#if UNIX_SOCK_SUPPORT
1258
+  if (man->settings.flags & MF_LISTEN_UNIX)
1259
+    {
1260
+      struct sockaddr_un remote;
1261
+      man->connection.sd_cli = socket_accept_unix (man->connection.sd_top, &remote);
1262
+      if (socket_defined (man->connection.sd_cli) && (man->settings.client_uid != -1 || man->settings.client_gid != -1))
1263
+	{
1264
+	  static const char err_prefix[] = "MANAGEMENT: unix domain socket client connection rejected --";
1265
+	  int uid, gid;
1266
+	  if (unix_socket_get_peer_uid_gid (man->connection.sd_cli, &uid, &gid))
1267
+	    {
1268
+	      if (man->settings.client_uid != -1 && man->settings.client_uid != uid)
1269
+		{
1270
+		  msg (D_MANAGEMENT, "%s UID of socket peer (%d) doesn't match required value (%d) as given by --management-client-user",
1271
+		       err_prefix, uid, man->settings.client_uid);
1272
+		  sd_close (&man->connection.sd_cli);
1273
+		}
1274
+	      if (man->settings.client_gid != -1 && man->settings.client_gid != gid)
1275
+		{
1276
+		  msg (D_MANAGEMENT, "%s GID of socket peer (%d) doesn't match required value (%d) as given by --management-client-group",
1277
+		       err_prefix, gid, man->settings.client_gid);
1278
+		  sd_close (&man->connection.sd_cli);
1279
+		}
1280
+	    }
1281
+	  else
1282
+	    {
1283
+	      msg (D_MANAGEMENT, "%s cannot get UID/GID of socket peer", err_prefix);
1284
+	      sd_close (&man->connection.sd_cli);
1285
+	    }
1286
+	}
1287
+    }
1288
+  else
1289
+#endif
1290
+    man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &act, false);
1291
+
1257 1292
   if (socket_defined (man->connection.sd_cli))
1258 1293
     {
1259 1294
       man->connection.remote = act.dest;
... ...
@@ -1285,12 +1338,19 @@ man_listen (struct management *man)
1285 1285
    */
1286 1286
   if (man->connection.sd_top == SOCKET_UNDEFINED)
1287 1287
     {
1288
-      man->connection.sd_top = create_socket_tcp ();
1289
-
1290
-      /*
1291
-       * Bind socket
1292
-       */
1293
-      socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
1288
+#if UNIX_SOCK_SUPPORT
1289
+      if (man->settings.flags & MF_LISTEN_UNIX)
1290
+	{
1291
+	  man_delete_unix_socket (man);
1292
+	  man->connection.sd_top = create_socket_unix ();
1293
+	  socket_bind_unix (man->connection.sd_top, &man->settings.local_unix, "MANAGEMENT");
1294
+	}
1295
+      else
1296
+#endif
1297
+	{
1298
+	  man->connection.sd_top = create_socket_tcp ();
1299
+	  socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
1300
+	}
1294 1301
 
1295 1302
       /*
1296 1303
        * Listen for connection
... ...
@@ -1304,8 +1364,16 @@ man_listen (struct management *man)
1304 1304
       set_nonblock (man->connection.sd_top);
1305 1305
       set_cloexec (man->connection.sd_top);
1306 1306
 
1307
-      msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
1308
-	   print_sockaddr (&man->settings.local, &gc));
1307
+#if UNIX_SOCK_SUPPORT
1308
+      if (man->settings.flags & MF_LISTEN_UNIX)
1309
+	{
1310
+	  msg (D_MANAGEMENT, "MANAGEMENT: unix domain socket listening on %s",
1311
+	       sockaddr_unix_name (&man->settings.local_unix, "NULL"));
1312
+	}
1313
+      else
1314
+#endif
1315
+	msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
1316
+	     print_sockaddr (&man->settings.local, &gc));
1309 1317
     }
1310 1318
 
1311 1319
 #ifdef WIN32
... ...
@@ -1645,6 +1713,8 @@ man_settings_init (struct man_settings *ms,
1645 1645
 		   const char *addr,
1646 1646
 		   const int port,
1647 1647
 		   const char *pass_file,
1648
+		   const char *client_user,
1649
+		   const char *client_group,
1648 1650
 		   const int log_history_cache,
1649 1651
 		   const int echo_buffer_size,
1650 1652
 		   const int state_buffer_size,
... ...
@@ -1657,6 +1727,8 @@ man_settings_init (struct man_settings *ms,
1657 1657
       CLEAR (*ms);
1658 1658
 
1659 1659
       ms->flags = flags;
1660
+      ms->client_uid = -1;
1661
+      ms->client_gid = -1;
1660 1662
 
1661 1663
       /*
1662 1664
        * Get username/password
... ...
@@ -1664,27 +1736,54 @@ man_settings_init (struct man_settings *ms,
1664 1664
       if (pass_file)
1665 1665
 	get_user_pass (&ms->up, pass_file, "Management", GET_USER_PASS_PASSWORD_ONLY);
1666 1666
 
1667
-      ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL);
1668
-
1669
-      /*
1670
-       * Initialize socket address
1671
-       */
1672
-      ms->local.sa.sin_family = AF_INET;
1673
-      ms->local.sa.sin_addr.s_addr = 0;
1674
-      ms->local.sa.sin_port = htons (port);
1675
-
1676 1667
       /*
1677
-       * Run management over tunnel, or
1678
-       * separate channel?
1668
+       * lookup client UID/GID if specified
1679 1669
        */
1680
-      if (streq (addr, "tunnel") && !(flags & MF_CONNECT_AS_CLIENT))
1670
+      if (client_user)
1671
+	{
1672
+	  struct user_state s;
1673
+	  get_user (client_user, &s);
1674
+	  ms->client_uid = user_state_uid (&s);
1675
+	  msg (D_MANAGEMENT, "MANAGEMENT: client_uid=%d", ms->client_uid);
1676
+	  ASSERT (ms->client_uid >= 0);
1677
+	}
1678
+      if (client_group)
1681 1679
 	{
1682
-	  ms->management_over_tunnel = true;
1680
+	  struct group_state s;
1681
+	  get_group (client_group, &s);
1682
+	  ms->client_gid = group_state_gid (&s);
1683
+	  msg (D_MANAGEMENT, "MANAGEMENT: client_gid=%d", ms->client_gid);
1684
+	  ASSERT (ms->client_gid >= 0);
1683 1685
 	}
1686
+
1687
+      ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL);
1688
+
1689
+#if UNIX_SOCK_SUPPORT
1690
+      if (ms->flags & MF_LISTEN_UNIX)
1691
+	sockaddr_unix_init (&ms->local_unix, addr);
1684 1692
       else
1693
+#endif
1685 1694
 	{
1686
-	  ms->local.sa.sin_addr.s_addr = getaddr
1687
-	    (GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
1695
+	  /*
1696
+	   * Initialize socket address
1697
+	   */
1698
+	  ms->local.sa.sin_family = AF_INET;
1699
+	  ms->local.sa.sin_addr.s_addr = 0;
1700
+	  ms->local.sa.sin_port = htons (port);
1701
+
1702
+	  /*
1703
+	   * Run management over tunnel, or
1704
+	   * separate channel?
1705
+	   */
1706
+	  if (streq (addr, "tunnel") && !(flags & MF_CONNECT_AS_CLIENT))
1707
+	    {
1708
+	      ms->management_over_tunnel = true;
1709
+	    }
1710
+	  else
1711
+	    {
1712
+	      ms->local.sa.sin_addr.s_addr = getaddr
1713
+		(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
1714
+	    }
1688 1715
 	}
1689 1716
       
1690 1717
       /*
... ...
@@ -1764,7 +1863,10 @@ man_connection_close (struct management *man)
1764 1764
   net_event_win32_close (&mc->ne32);
1765 1765
 #endif
1766 1766
   if (socket_defined (mc->sd_top))
1767
-    man_close_socket (man, mc->sd_top);
1767
+    {
1768
+      man_close_socket (man, mc->sd_top);
1769
+      man_delete_unix_socket (man);
1770
+    }
1768 1771
   if (socket_defined (mc->sd_cli))
1769 1772
     man_close_socket (man, mc->sd_cli);
1770 1773
   if (mc->in)
... ...
@@ -1798,6 +1900,8 @@ management_open (struct management *man,
1798 1798
 		 const char *addr,
1799 1799
 		 const int port,
1800 1800
 		 const char *pass_file,
1801
+		 const char *client_user,
1802
+		 const char *client_group,
1801 1803
 		 const int log_history_cache,
1802 1804
 		 const int echo_buffer_size,
1803 1805
 		 const int state_buffer_size,
... ...
@@ -1815,6 +1919,8 @@ management_open (struct management *man,
1815 1815
 		     addr,
1816 1816
 		     port,
1817 1817
 		     pass_file,
1818
+		     client_user,
1819
+		     client_group,
1818 1820
 		     log_history_cache,
1819 1821
 		     echo_buffer_size,
1820 1822
 		     state_buffer_size,
... ...
@@ -202,12 +202,17 @@ struct man_settings {
202 202
   bool defined;
203 203
   unsigned int flags; /* MF_x flags */
204 204
   struct openvpn_sockaddr local;
205
+#if UNIX_SOCK_SUPPORT
206
+  struct sockaddr_un local_unix;
207
+#endif
205 208
   bool management_over_tunnel;
206 209
   struct user_pass up;
207 210
   int log_history_cache;
208 211
   int echo_buffer_size;
209 212
   int state_buffer_size;
210 213
   char *write_peer_info_file;
214
+  int client_uid;
215
+  int client_gid;
211 216
 
212 217
 /* flags for handling the management interface "signal" command */
213 218
 # define MANSIG_IGNORE_USR1_HUP  (1<<0)
... ...
@@ -295,10 +300,14 @@ struct management *management_init (void);
295 295
 #ifdef MANAGEMENT_PF
296 296
 # define MF_CLIENT_PF         (1<<7)
297 297
 #endif
298
+# define MF_LISTEN_UNIX       (1<<8)
299
+
298 300
 bool management_open (struct management *man,
299 301
 		      const char *addr,
300 302
 		      const int port,
301 303
 		      const char *pass_file,
304
+		      const char *client_user,
305
+		      const char *client_group,
302 306
 		      const int log_history_cache,
303 307
 		      const int echo_buffer_size,
304 308
 		      const int state_buffer_size,
... ...
@@ -82,7 +82,7 @@ get_user (const char *username, struct user_state *state)
82 82
       state->username = username;
83 83
       ret = true;
84 84
 #else
85
-      msg (M_FATAL, "Sorry but I can't setuid to '%s' because this operating system doesn't appear to support the getpwname() or setuid() system calls", username);
85
+      msg (M_FATAL, "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username);
86 86
 #endif
87 87
     }
88 88
   return ret;
... ...
@@ -117,7 +117,7 @@ get_group (const char *groupname, struct group_state *state)
117 117
       state->groupname = groupname;
118 118
       ret = true;
119 119
 #else
120
-      msg (M_FATAL, "Sorry but I can't setgid to '%s' because this operating system doesn't appear to support the getgrnam() or setgid() system calls", groupname);
120
+      msg (M_FATAL, "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname);
121 121
 #endif
122 122
     }
123 123
   return ret;
... ...
@@ -119,7 +119,7 @@ void warn_if_group_others_accessible(const char* filename);
119 119
 
120 120
 /* interpret the status code returned by system()/execve() */
121 121
 bool system_ok(int);
122
-int system_executed (int stat);
122
+bool system_executed (int stat);
123 123
 const char *system_error_message (int, struct gc_arena *gc);
124 124
 
125 125
 /* wrapper around the execve() call */
... ...
@@ -330,4 +330,28 @@ void argv_printf_cat (struct argv *a, const char *format, ...)
330 330
 #endif
331 331
   ;
332 332
 
333
+/*
334
+ * Extract UID or GID
335
+ */
336
+
337
+static inline int
338
+user_state_uid (const struct user_state *s)
339
+{
340
+#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
341
+  if (s->pw)
342
+    return s->pw->pw_uid;
343
+#endif
344
+  return -1;
345
+}
346
+
347
+static inline int
348
+group_state_gid (const struct group_state *s)
349
+{
350
+#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
351
+  if (s->gr)
352
+    return s->gr->gr_gid;
353
+#endif
354
+  return -1;
355
+}
356
+
333 357
 #endif
... ...
@@ -181,7 +181,9 @@ openvpn \- secure IP tunnel daemon.
181 181
 [\ \fB\-\-suppress-timestamps\fR\ ]
182 182
 [\ \fB\-\-lport\fR\ \fIport\fR\ ]
183 183
 [\ \fB\-\-management\-client\-auth\fR\ ]
184
+[\ \fB\-\-management\-client\-group\fR\ \fIg\fR\ ]
184 185
 [\ \fB\-\-management\-client\-pf\fR\ ]
186
+[\ \fB\-\-management\-client\-user\fR\ \fIu\fR\ ]
185 187
 [\ \fB\-\-management\-forget\-disconnect\fR\ ]
186 188
 [\ \fB\-\-management\-hold\fR\ ]
187 189
 [\ \fB\-\-management\-log\-cache\fR\ \fIn\fR\ ]
... ...
@@ -2455,6 +2457,19 @@ or "stdin" to prompt from standard input.  The password
2455 2455
 provided will set the password which TCP clients will need
2456 2456
 to provide in order to access management functions.
2457 2457
 
2458
+The management interface can also listen on a unix domain socket,
2459
+for those platforms that support it.  To use a unix domain socket, specify
2460
+the unix socket pathname in place of
2461
+.B IP
2462
+and set
2463
+.B port
2464
+to 'unix'.  While the default behavior is to create a unix domain socket
2465
+that may be connected to by any process, the
2466
+.B --management-client-user
2467
+and
2468
+.B --management-client-group
2469
+directives can be used to restrict access.
2470
+
2458 2471
 The management interface provides a special mode where the TCP
2459 2472
 management link can operate over the tunnel itself.  To enable this mode,
2460 2473
 set
... ...
@@ -2532,6 +2547,18 @@ filter file for each connecting client.  See management-notes.txt
2532 2532
 in OpenVPN distribution for detailed notes.
2533 2533
 .\"*********************************************************
2534 2534
 .TP
2535
+.B --management-client-user u
2536
+When the management interface is listening on a unix domain socket,
2537
+only allow connections from user
2538
+.B u.
2539
+.\"*********************************************************
2540
+.TP
2541
+.B --management-client-group g
2542
+When the management interface is listening on a unix domain socket,
2543
+only allow connections from group
2544
+.B g.
2545
+.\"*********************************************************
2546
+.TP
2535 2547
 .B --plugin module-pathname [init-string]
2536 2548
 Load plug-in module from the file
2537 2549
 .B module-pathname,
... ...
@@ -311,6 +311,10 @@ static const char usage_message[] =
311 311
   "--management ip port [pass] : Enable a TCP server on ip:port to handle\n"
312 312
   "                  management functions.  pass is a password file\n"
313 313
   "                  or 'stdin' to prompt from console.\n"
314
+#if UNIX_SOCK_SUPPORT
315
+  "                  To listen on a unix domain socket, specific the pathname\n"
316
+  "                  in place of ip and use 'unix' as the port number.\n"
317
+#endif
314 318
   "--management-client : Management interface will connect as a TCP client to\n"
315 319
   "                      ip/port rather than listen as a TCP server.\n"
316 320
   "--management-query-passwords : Query management channel for private key\n"
... ...
@@ -322,6 +326,12 @@ static const char usage_message[] =
322 322
   "                                 event occurs.\n"
323 323
   "--management-log-cache n : Cache n lines of log file history for usage\n"
324 324
   "                  by the management channel.\n"
325
+#if UNIX_SOCK_SUPPORT
326
+  "--management-client-user u  : When management interface is a unix socket, only\n"
327
+  "                              allow connections from user u.\n"
328
+  "--management-client-group g : When management interface is a unix socket, only\n"
329
+  "                              allow connections from group g.\n"
330
+#endif
325 331
 #ifdef MANAGEMENT_DEF_AUTH
326 332
   "--management-client-auth : gives management interface client the responsibility\n"
327 333
   "                           to authenticate clients after their client certificate\n"
... ...
@@ -1240,6 +1250,8 @@ show_settings (const struct options *o)
1240 1240
   SHOW_INT (management_log_history_cache);
1241 1241
   SHOW_INT (management_echo_buffer_size);
1242 1242
   SHOW_STR (management_write_peer_info_file);
1243
+  SHOW_STR (management_client_user);
1244
+  SHOW_STR (management_client_group);
1243 1245
   SHOW_INT (management_flags);
1244 1246
 #endif
1245 1247
 #ifdef ENABLE_PLUGIN
... ...
@@ -1554,6 +1566,14 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
1554 1554
        || options->management_write_peer_info_file
1555 1555
        || options->management_log_history_cache != defaults.management_log_history_cache))
1556 1556
     msg (M_USAGE, "--management is not specified, however one or more options which modify the behavior of --management were specified");
1557
+
1558
+  if ((options->management_flags & (MF_LISTEN_UNIX|MF_CONNECT_AS_CLIENT))
1559
+      == (MF_LISTEN_UNIX|MF_CONNECT_AS_CLIENT))
1560
+    msg (M_USAGE, "--management-client does not support unix domain sockets");
1561
+
1562
+  if ((options->management_client_user || options->management_client_group)
1563
+      && !(options->management_flags & MF_LISTEN_UNIX))
1564
+    msg (M_USAGE, "--management-client-(user|group) can only be used on unix domain sockets");
1557 1565
 #endif
1558 1566
 
1559 1567
   /*
... ...
@@ -3319,14 +3339,26 @@ add_option (struct options *options,
3319 3319
 #ifdef ENABLE_MANAGEMENT
3320 3320
   else if (streq (p[0], "management") && p[1] && p[2])
3321 3321
     {
3322
-      int port;
3322
+      int port = 0;
3323 3323
 
3324 3324
       VERIFY_PERMISSION (OPT_P_GENERAL);
3325
-      port = atoi (p[2]);
3326
-      if (!legal_ipv4_port (port))
3325
+      if (streq (p[2], "unix"))
3327 3326
 	{
3328
-	  msg (msglevel, "port number associated with --management directive is out of range");
3327
+#if UNIX_SOCK_SUPPORT
3328
+	  options->management_flags |= MF_LISTEN_UNIX;
3329
+#else
3330
+	  msg (msglevel, "MANAGEMENT: this platform does not support unix domain sockets");
3329 3331
 	  goto err;
3332
+#endif
3333
+	}
3334
+      else
3335
+	{
3336
+	  port = atoi (p[2]);
3337
+	  if (!legal_ipv4_port (port))
3338
+	    {
3339
+	      msg (msglevel, "port number associated with --management directive is out of range");
3340
+	      goto err;
3341
+	    }
3330 3342
 	}
3331 3343
 
3332 3344
       options->management_addr = p[1];
... ...
@@ -3336,6 +3368,16 @@ add_option (struct options *options,
3336 3336
 	  options->management_user_pass = p[3];
3337 3337
 	}
3338 3338
     }
3339
+  else if (streq (p[0], "management-client-user") && p[1])
3340
+    {
3341
+      VERIFY_PERMISSION (OPT_P_GENERAL);
3342
+      options->management_client_user = p[1];
3343
+    }
3344
+  else if (streq (p[0], "management-client-group") && p[1])
3345
+    {
3346
+      VERIFY_PERMISSION (OPT_P_GENERAL);
3347
+      options->management_client_group = p[1];
3348
+    }
3339 3349
   else if (streq (p[0], "management-query-passwords"))
3340 3350
     {
3341 3351
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -319,6 +319,9 @@ struct options
319 319
   int management_state_buffer_size;
320 320
   const char *management_write_peer_info_file;
321 321
 
322
+  const char *management_client_user;
323
+  const char *management_client_group;
324
+
322 325
   /* Mask of MF_ values of manage.h */
323 326
   unsigned int management_flags;
324 327
 #endif
... ...
@@ -610,9 +613,9 @@ char *options_string (const struct options *o,
610 610
 		      bool remote,
611 611
 		      struct gc_arena *gc);
612 612
 
613
-int options_cmp_equal_safe (char *actual, const char *expected, size_t actual_n);
613
+bool options_cmp_equal_safe (char *actual, const char *expected, size_t actual_n);
614 614
 void options_warning_safe (char *actual, const char *expected, size_t actual_n);
615
-int options_cmp_equal (char *actual, const char *expected);
615
+bool options_cmp_equal (char *actual, const char *expected);
616 616
 void options_warning (char *actual, const char *expected);
617 617
 
618 618
 #endif
... ...
@@ -2627,3 +2627,125 @@ socket_set (struct link_socket *s,
2627 2627
     }
2628 2628
   return rwflags;
2629 2629
 }
2630
+
2631
+void
2632
+sd_close (socket_descriptor_t *sd)
2633
+{
2634
+  if (sd && socket_defined (*sd))
2635
+    {
2636
+      openvpn_close_socket (*sd);
2637
+      *sd = SOCKET_UNDEFINED;
2638
+    }
2639
+}
2640
+
2641
+#if UNIX_SOCK_SUPPORT
2642
+
2643
+/*
2644
+ * code for unix domain sockets
2645
+ */
2646
+
2647
+const char *
2648
+sockaddr_unix_name (const struct sockaddr_un *local, const char *null)
2649
+{
2650
+  if (local && local->sun_family == PF_UNIX)
2651
+    return local->sun_path;
2652
+  else
2653
+    return null;
2654
+}
2655
+
2656
+socket_descriptor_t
2657
+create_socket_unix (void)
2658
+{
2659
+  socket_descriptor_t sd;
2660
+
2661
+  if ((sd = socket (PF_UNIX, SOCK_STREAM, 0)) < 0)
2662
+    msg (M_SOCKERR, "Cannot create unix domain socket");
2663
+  return sd;
2664
+}
2665
+
2666
+void
2667
+socket_bind_unix (socket_descriptor_t sd,
2668
+		  struct sockaddr_un *local,
2669
+		  const char *prefix)
2670
+{
2671
+  struct gc_arena gc = gc_new ();
2672
+
2673
+#ifdef HAVE_UMASK
2674
+  const mode_t orig_umask = umask (0);
2675
+#endif
2676
+
2677
+  if (bind (sd, (struct sockaddr *) local, sizeof (struct sockaddr_un)))
2678
+    {
2679
+      const int errnum = openvpn_errno_socket ();
2680
+      msg (M_FATAL, "%s: Socket bind[%d] failed on unix domain socket %s: %s",
2681
+	   prefix,
2682
+	   (int)sd,
2683
+           sockaddr_unix_name (local, "NULL"),
2684
+           strerror_ts (errnum, &gc));
2685
+    }
2686
+
2687
+#ifdef HAVE_UMASK
2688
+  umask (orig_umask);
2689
+#endif
2690
+
2691
+  gc_free (&gc);
2692
+}
2693
+
2694
+socket_descriptor_t
2695
+socket_accept_unix (socket_descriptor_t sd,
2696
+		    struct sockaddr_un *remote)
2697
+{
2698
+  socklen_t remote_len = sizeof (struct sockaddr_un);
2699
+  socket_descriptor_t ret;
2700
+
2701
+  CLEAR (*remote);
2702
+  ret = accept (sd, (struct sockaddr *) remote, &remote_len);
2703
+  return ret;
2704
+}
2705
+
2706
+void
2707
+sockaddr_unix_init (struct sockaddr_un *local, const char *path)
2708
+{
2709
+  local->sun_family = PF_UNIX;
2710
+  strncpynt (local->sun_path, path, sizeof (local->sun_path));
2711
+}
2712
+
2713
+void
2714
+socket_delete_unix (const struct sockaddr_un *local)
2715
+{
2716
+  const char *name = sockaddr_unix_name (local, NULL);
2717
+#ifdef HAVE_UNLINK
2718
+  if (name && strlen (name))
2719
+    unlink (name);
2720
+#endif
2721
+}
2722
+
2723
+bool
2724
+unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *gid)
2725
+{
2726
+#ifdef HAVE_GETPEEREID
2727
+  uid_t u;
2728
+  gid_t g;
2729
+  if (getpeereid (sd, &u, &g) == -1) 
2730
+    return false;
2731
+  if (uid)
2732
+    *uid = u;
2733
+  if (gid)
2734
+    *gid = g;
2735
+  return true;
2736
+#elif defined(SO_PEERCRED)
2737
+  struct ucred peercred;
2738
+  socklen_t so_len = sizeof(peercred);
2739
+  if (getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) 
2740
+    return false;
2741
+  if (uid)
2742
+    *uid = peercred.uid;
2743
+  if (gid)
2744
+    *gid = peercred.gid;
2745
+  return true;
2746
+#else
2747
+  return false;
2748
+#endif
2749
+}
2750
+
2751
+#endif
... ...
@@ -322,6 +322,8 @@ void frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto);
322 322
 
323 323
 void link_socket_close (struct link_socket *sock);
324 324
 
325
+void sd_close (socket_descriptor_t *sd);
326
+
325 327
 #define PS_SHOW_PORT_IF_DEFINED (1<<0)
326 328
 #define PS_SHOW_PORT            (1<<1)
327 329
 #define PS_SHOW_PKTINFO         (1<<2)
... ...
@@ -408,6 +410,27 @@ socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
408 408
 				      struct link_socket_actual *act,
409 409
 				      const bool nowait);
410 410
 
411
+#if UNIX_SOCK_SUPPORT
412
+
413
+socket_descriptor_t create_socket_unix (void);
414
+
415
+void socket_bind_unix (socket_descriptor_t sd,
416
+		       struct sockaddr_un *local,
417
+		       const char *prefix);
418
+
419
+socket_descriptor_t socket_accept_unix (socket_descriptor_t sd,
420
+					struct sockaddr_un *remote);
421
+
422
+void sockaddr_unix_init (struct sockaddr_un *local, const char *path);
423
+
424
+const char *sockaddr_unix_name (const struct sockaddr_un *local, const char *null);
425
+
426
+void socket_delete_unix (const struct sockaddr_un *local);
427
+
428
+bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *gid);
429
+
430
+#endif
431
+
411 432
 /*
412 433
  * DNS resolution
413 434
  */
... ...
@@ -88,6 +88,10 @@
88 88
 #include <sys/socket.h>
89 89
 #endif
90 90
 
91
+#ifdef HAVE_SYS_UN_H
92
+#include <sys/un.h>
93
+#endif
94
+
91 95
 #ifdef HAVE_SYS_IOCTL_H
92 96
 #include <sys/ioctl.h>
93 97
 #endif
... ...
@@ -516,6 +520,15 @@ socket_defined (const socket_descriptor_t sd)
516 516
 #endif
517 517
 
518 518
 /*
519
+ * Do we support Unix domain sockets?
520
+ */
521
+#if defined(PF_UNIX) && !defined(WIN32)
522
+#define UNIX_SOCK_SUPPORT 1
523
+#else
524
+#define UNIX_SOCK_SUPPORT 0
525
+#endif
526
+
527
+/*
519 528
  * Don't compile the struct buffer_list code unless something needs it
520 529
  */
521 530
 #if defined(ENABLE_MANAGEMENT) || defined(ENABLE_PF)
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc12])
2
+define(PRODUCT_VERSION,[2.1_rc12a])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])