From 86f5c7c9d540096bcabf33b49303090e6638a99d Mon Sep 17 00:00:00 2001 From: james Date: Fri, 10 Apr 2009 21:33:14 +0000 Subject: Allow "management-client" directive to be used with unix domain sockets. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4128 e7ae566f-a301-0410-adde-c780ea21d3b5 --- manage.c | 112 +++++++++++++++++++++++++++++++++++++++++--------------------- manage.h | 2 +- options.c | 8 ++--- socket.c | 10 ++++++ socket.h | 3 ++ 5 files changed, 91 insertions(+), 44 deletions(-) diff --git a/manage.c b/manage.c index cff4348..1dd2825 100644 --- a/manage.c +++ b/manage.c @@ -230,7 +230,7 @@ static void man_delete_unix_socket (struct management *man) { #if UNIX_SOCK_SUPPORT - if (man->settings.flags & MF_LISTEN_UNIX) + if ((man->settings.flags & (MF_UNIX_SOCK|MF_CONNECT_AS_CLIENT)) == MF_UNIX_SOCK) socket_delete_unix (&man->settings.local_unix); #endif } @@ -1287,7 +1287,7 @@ man_new_connection_post (struct management *man, const char *description) #endif #if UNIX_SOCK_SUPPORT - if (man->settings.flags & MF_LISTEN_UNIX) + if (man->settings.flags & MF_UNIX_SOCK) { msg (D_MANAGEMENT, "MANAGEMENT: %s %s", description, @@ -1309,6 +1309,39 @@ man_new_connection_post (struct management *man, const char *description) gc_free (&gc); } +#if UNIX_SOCK_SUPPORT +static bool +man_verify_unix_peer_uid_gid (struct management *man, const socket_descriptor_t sd) +{ + if (socket_defined (sd) && (man->settings.client_uid != -1 || man->settings.client_gid != -1)) + { + static const char err_prefix[] = "MANAGEMENT: unix domain socket client connection rejected --"; + int uid, gid; + if (unix_socket_get_peer_uid_gid (man->connection.sd_cli, &uid, &gid)) + { + if (man->settings.client_uid != -1 && man->settings.client_uid != uid) + { + msg (D_MANAGEMENT, "%s UID of socket peer (%d) doesn't match required value (%d) as given by --management-client-user", + err_prefix, uid, man->settings.client_uid); + return false; + } + if (man->settings.client_gid != -1 && man->settings.client_gid != gid) + { + msg (D_MANAGEMENT, "%s GID of socket peer (%d) doesn't match required value (%d) as given by --management-client-group", + err_prefix, gid, man->settings.client_gid); + return false; + } + } + else + { + msg (D_MANAGEMENT, "%s cannot get UID/GID of socket peer", err_prefix); + return false; + } + } + return true; +} +#endif + static void man_accept (struct management *man) { @@ -1319,35 +1352,12 @@ man_accept (struct management *man) * Accept the TCP or Unix domain socket client. */ #if UNIX_SOCK_SUPPORT - if (man->settings.flags & MF_LISTEN_UNIX) + if (man->settings.flags & MF_UNIX_SOCK) { struct sockaddr_un remote; man->connection.sd_cli = socket_accept_unix (man->connection.sd_top, &remote); - if (socket_defined (man->connection.sd_cli) && (man->settings.client_uid != -1 || man->settings.client_gid != -1)) - { - static const char err_prefix[] = "MANAGEMENT: unix domain socket client connection rejected --"; - int uid, gid; - if (unix_socket_get_peer_uid_gid (man->connection.sd_cli, &uid, &gid)) - { - if (man->settings.client_uid != -1 && man->settings.client_uid != uid) - { - msg (D_MANAGEMENT, "%s UID of socket peer (%d) doesn't match required value (%d) as given by --management-client-user", - err_prefix, uid, man->settings.client_uid); - sd_close (&man->connection.sd_cli); - } - if (man->settings.client_gid != -1 && man->settings.client_gid != gid) - { - msg (D_MANAGEMENT, "%s GID of socket peer (%d) doesn't match required value (%d) as given by --management-client-group", - err_prefix, gid, man->settings.client_gid); - sd_close (&man->connection.sd_cli); - } - } - else - { - msg (D_MANAGEMENT, "%s cannot get UID/GID of socket peer", err_prefix); - sd_close (&man->connection.sd_cli); - } - } + if (!man_verify_unix_peer_uid_gid (man, man->connection.sd_cli)) + sd_close (&man->connection.sd_cli); } else #endif @@ -1385,7 +1395,7 @@ man_listen (struct management *man) if (man->connection.sd_top == SOCKET_UNDEFINED) { #if UNIX_SOCK_SUPPORT - if (man->settings.flags & MF_LISTEN_UNIX) + if (man->settings.flags & MF_UNIX_SOCK) { man_delete_unix_socket (man); man->connection.sd_top = create_socket_unix (); @@ -1411,7 +1421,7 @@ man_listen (struct management *man) set_cloexec (man->connection.sd_top); #if UNIX_SOCK_SUPPORT - if (man->settings.flags & MF_LISTEN_UNIX) + if (man->settings.flags & MF_UNIX_SOCK) { msg (D_MANAGEMENT, "MANAGEMENT: unix domain socket listening on %s", sockaddr_unix_name (&man->settings.local_unix, "NULL")); @@ -1442,12 +1452,30 @@ man_connect (struct management *man) man->connection.state = MS_INITIAL; man->connection.sd_top = SOCKET_UNDEFINED; - man->connection.sd_cli = create_socket_tcp (); - - status = openvpn_connect (man->connection.sd_cli, - &man->settings.local, - 5, - &signal_received); +#if UNIX_SOCK_SUPPORT + if (man->settings.flags & MF_UNIX_SOCK) + { + man->connection.sd_cli = create_socket_unix (); + status = socket_connect_unix (man->connection.sd_cli, &man->settings.local_unix); + if (!status && !man_verify_unix_peer_uid_gid (man, man->connection.sd_cli)) + { +#ifdef EPERM + status = EPERM; +#else + status = 1; +#endif + sd_close (&man->connection.sd_cli); + } + } + else +#endif + { + man->connection.sd_cli = create_socket_tcp (); + status = openvpn_connect (man->connection.sd_cli, + &man->settings.local, + 5, + &signal_received); + } if (signal_received) { @@ -1457,6 +1485,16 @@ man_connect (struct management *man) if (status) { +#if UNIX_SOCK_SUPPORT + if (man->settings.flags & MF_UNIX_SOCK) + { + msg (D_LINK_ERRORS, + "MANAGEMENT: connect to unix socket %s failed: %s", + sockaddr_unix_name (&man->settings.local_unix, "NULL"), + strerror_ts (status, &gc)); + } + else +#endif msg (D_LINK_ERRORS, "MANAGEMENT: connect to %s failed: %s", print_sockaddr (&man->settings.local, &gc), @@ -1805,7 +1843,7 @@ man_settings_init (struct man_settings *ms, ms->write_peer_info_file = string_alloc (write_peer_info_file, NULL); #if UNIX_SOCK_SUPPORT - if (ms->flags & MF_LISTEN_UNIX) + if (ms->flags & MF_UNIX_SOCK) sockaddr_unix_init (&ms->local_unix, addr); else #endif diff --git a/manage.h b/manage.h index 66fb7d1..9114184 100644 --- a/manage.h +++ b/manage.h @@ -307,7 +307,7 @@ struct management *management_init (void); #ifdef MANAGEMENT_PF # define MF_CLIENT_PF (1<<7) #endif -# define MF_LISTEN_UNIX (1<<8) +# define MF_UNIX_SOCK (1<<8) bool management_open (struct management *man, const char *addr, diff --git a/options.c b/options.c index 758a078..f2c7da8 100644 --- a/options.c +++ b/options.c @@ -1585,12 +1585,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne || options->management_log_history_cache != defaults.management_log_history_cache)) msg (M_USAGE, "--management is not specified, however one or more options which modify the behavior of --management were specified"); - if ((options->management_flags & (MF_LISTEN_UNIX|MF_CONNECT_AS_CLIENT)) - == (MF_LISTEN_UNIX|MF_CONNECT_AS_CLIENT)) - msg (M_USAGE, "--management-client does not support unix domain sockets"); - if ((options->management_client_user || options->management_client_group) - && !(options->management_flags & MF_LISTEN_UNIX)) + && !(options->management_flags & MF_UNIX_SOCK)) msg (M_USAGE, "--management-client-(user|group) can only be used on unix domain sockets"); #endif @@ -3391,7 +3387,7 @@ add_option (struct options *options, if (streq (p[2], "unix")) { #if UNIX_SOCK_SUPPORT - options->management_flags |= MF_LISTEN_UNIX; + options->management_flags |= MF_UNIX_SOCK; #else msg (msglevel, "MANAGEMENT: this platform does not support unix domain sockets"); goto err; diff --git a/socket.c b/socket.c index ba1e367..dacb2c4 100644 --- a/socket.c +++ b/socket.c @@ -2703,6 +2703,16 @@ socket_accept_unix (socket_descriptor_t sd, return ret; } +int +socket_connect_unix (socket_descriptor_t sd, + struct sockaddr_un *remote) +{ + int status = connect (sd, (struct sockaddr *) remote, sizeof (struct sockaddr_un)); + if (status) + status = openvpn_errno_socket (); + return status; +} + void sockaddr_unix_init (struct sockaddr_un *local, const char *path) { diff --git a/socket.h b/socket.h index a8c7097..84d9b4f 100644 --- a/socket.h +++ b/socket.h @@ -421,6 +421,9 @@ void socket_bind_unix (socket_descriptor_t sd, socket_descriptor_t socket_accept_unix (socket_descriptor_t sd, struct sockaddr_un *remote); +int socket_connect_unix (socket_descriptor_t sd, + struct sockaddr_un *remote); + void sockaddr_unix_init (struct sockaddr_un *local, const char *path); const char *sockaddr_unix_name (const struct sockaddr_un *local, const char *null); -- cgit