From edf939632c9a1dbab4e769f0c23fe393d7fc8a6a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 12 Apr 2013 17:09:06 -0400 Subject: Add support for per-service sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way different processes running as the same user can be configured as different servervices Signed-off-by: Simo Sorce Reviewed-by: Günther Deschner --- proxy/Makefile.am | 1 + proxy/conf_macros.m4 | 6 +++--- proxy/src/client/gpm_common.c | 8 +++++++- proxy/src/gp_common.c | 37 +++++++++++++++++++++++++++++++++++++ proxy/src/gp_common.h | 2 ++ proxy/src/gp_config.c | 9 +++++++++ proxy/src/gp_creds.c | 6 ++++++ proxy/src/gp_proxy.h | 11 ++++++++++- proxy/src/gp_socket.c | 28 +++++++++++++++++++++++----- proxy/src/gssproxy.c | 41 ++++++++++++++++++++++++++++++----------- 10 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 proxy/src/gp_common.c diff --git a/proxy/Makefile.am b/proxy/Makefile.am index c814ab8..04027d6 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -154,6 +154,7 @@ gssproxy_SOURCES = \ src/gp_export.c \ src/gp_debug.c \ src/gp_log.c \ + src/gp_common.c \ src/gp_rpc_accept_sec_context.c \ src/gp_rpc_release_handle.c \ src/gp_rpc_acquire_cred.c \ diff --git a/proxy/conf_macros.m4 b/proxy/conf_macros.m4 index f2d3755..a92c24a 100644 --- a/proxy/conf_macros.m4 +++ b/proxy/conf_macros.m4 @@ -46,12 +46,12 @@ AC_DEFUN([WITH_PUBCONF_PATH], AC_DEFUN([WITH_SOCKET_NAME], [ AC_ARG_WITH([socket-name], [AC_HELP_STRING([--with-socket-name=PATH], - [Name of the GSS Proxy socket file [/var/run/gssproxy.sock]] + [Name of the GSS Proxy socket file [/var/lib/gssproxy/default.sock]] ) ] ) - gp_socket_name="\"VARDIR\"/run/gssproxy.sock" - socketname="${localstatedir}/run/gssproxy.sock" + gp_socket_name="\"VARDIR\"/lib/gssproxy/default.sock" + socketname="${localstatedir}/lib/gssproxy/default.sock" if test x"$with_socket_name" != x; then gp_socket_name=$with_socket_name socketname=$with_socket_name diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c index d9015f6..8ac1a2a 100644 --- a/proxy/src/client/gpm_common.c +++ b/proxy/src/client/gpm_common.c @@ -65,9 +65,15 @@ static void gpm_init_once(void) static int get_pipe_name(struct gpm_ctx *gpmctx, char *name) { + const char *socket; int ret; - ret = snprintf(name, PATH_MAX, "%s", GP_SOCKET_NAME); + socket = getenv("GSSPROXY_SOCKET"); + if (!socket) { + socket = GP_SOCKET_NAME; + } + + ret = snprintf(name, PATH_MAX, "%s", socket); if (ret < 0 || ret >= PATH_MAX) { return ENAMETOOLONG; } diff --git a/proxy/src/gp_common.c b/proxy/src/gp_common.c new file mode 100644 index 0000000..f4ebc5e --- /dev/null +++ b/proxy/src/gp_common.c @@ -0,0 +1,37 @@ +/* + GSS-PROXY + + Copyright (C) 2013 Red Hat, Inc. + Copyright (C) 2013 Simo Sorce + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include "gp_common.h" + +bool gp_same(const char *a, const char *b) +{ + if ((a == b) || strcmp(a, b) == 0) { + return true; + } + + return false; +} diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h index f4a8a58..25cd278 100644 --- a/proxy/src/gp_common.h +++ b/proxy/src/gp_common.h @@ -65,6 +65,8 @@ /* max out at 1MB for now */ #define MAX_RPC_SIZE 1024*1024 +bool gp_same(const char *a, const char *b); + #include "rpcgen/gss_proxy.h" union gp_rpc_arg { diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c index 012094a..630f56d 100644 --- a/proxy/src/gp_config.c +++ b/proxy/src/gp_config.c @@ -184,6 +184,15 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) } } + value = gp_config_get_string(ctx, secname, "socket"); + if (value != NULL) { + cfg->svcs[n]->socket = strdup(value); + if (!cfg->svcs[n]->socket) { + ret = ENOMEM; + goto done; + } + } + ret = setup_service_creds_handle(cfg->svcs[n]); if (ret) { goto done; diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c index 4a731b0..e6c12a5 100644 --- a/proxy/src/gp_creds.c +++ b/proxy/src/gp_creds.c @@ -95,12 +95,18 @@ struct gp_service *gp_creds_match_conn(struct gssproxy_ctx *gpctx, struct gp_conn *conn) { struct gp_creds *gcs; + const char *socket; int i; gcs = gp_conn_get_creds(conn); + socket = gp_conn_get_socket(conn); for (i = 0; i < gpctx->config->num_svcs; i++) { if (gpctx->config->svcs[i]->euid == gcs->ucred.uid) { + if (gpctx->config->svcs[i]->socket && + gp_same(socket, gpctx->config->svcs[i]->socket)) { + continue; + } return gpctx->config->svcs[i]; } } diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h index 8f5a059..6764f6a 100644 --- a/proxy/src/gp_proxy.h +++ b/proxy/src/gp_proxy.h @@ -51,6 +51,7 @@ struct gp_service { uid_t euid; bool trusted; bool kernel_nfsd; + char *socket; uint32_t mechs; struct gp_cred_krb5 krb5; @@ -76,6 +77,12 @@ struct gssproxy_ctx { verto_ctx *vctx; }; +struct gp_sock_ctx { + struct gssproxy_ctx *gpctx; + const char *socket; + int fd; +}; + struct gp_conn; /* from gp_config.c */ @@ -91,12 +98,14 @@ void init_proc_nfsd(struct gp_config *cfg); void write_pid(void); /* from gp_socket.c */ -int init_unix_socket(const char *file_name); +struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx, + const char *file_name); void accept_sock_conn(verto_ctx *vctx, verto_ev *ev); void gp_conn_free(struct gp_conn *conn); void gp_socket_send_data(verto_ctx *vctx, struct gp_conn *conn, uint8_t *buffer, size_t buflen); struct gp_creds *gp_conn_get_creds(struct gp_conn *conn); +const char *gp_conn_get_socket(struct gp_conn *conn); /* from gp_workers.c */ int gp_workers_init(struct gssproxy_ctx *gpctx); diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c index 20a13c5..02bc882 100644 --- a/proxy/src/gp_socket.c +++ b/proxy/src/gp_socket.c @@ -55,7 +55,7 @@ struct unix_sock_conn { }; struct gp_conn { - struct gssproxy_ctx *gpctx; + struct gp_sock_ctx *sock_ctx; struct unix_sock_conn us; struct gp_creds creds; SEC_CTX secctx; @@ -73,6 +73,11 @@ struct gp_creds *gp_conn_get_creds(struct gp_conn *conn) return &conn->creds; } +const char *gp_conn_get_socket(struct gp_conn *conn) +{ + return conn->sock_ctx->socket; +} + void gp_conn_free(struct gp_conn *conn) { if (!conn) return; @@ -118,13 +123,20 @@ static int set_fd_flags(int fd, int flags) return 0; } -int init_unix_socket(const char *file_name) +struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx, + const char *file_name) { struct sockaddr_un addr = {0}; + struct gp_sock_ctx *sock_ctx; mode_t old_mode; int ret = 0; int fd = -1; + sock_ctx = calloc(1, sizeof(struct gp_sock_ctx)); + if (!sock_ctx) { + return NULL; + } + /* can't bind if an old socket is around */ unlink(file_name); @@ -177,9 +189,15 @@ done: close(fd); fd = -1; } + safefree(sock_ctx); + } else { + sock_ctx->gpctx = gpctx; + sock_ctx->socket = file_name; + sock_ctx->fd = fd; } umask(old_mode); - return fd; + + return sock_ctx; } static int get_peercred(int fd, struct gp_conn *conn) @@ -334,7 +352,7 @@ static void gp_socket_read(verto_ctx *vctx, verto_ev *ev) if (rbuf->pos == rbuf->size) { /* got all data, hand over packet */ - ret = gp_query_new(rbuf->conn->gpctx->workers, rbuf->conn, + ret = gp_query_new(rbuf->conn->sock_ctx->gpctx->workers, rbuf->conn, rbuf->data, rbuf->size); if (ret != 0) { /* internal error, not much we can do */ @@ -472,7 +490,7 @@ void accept_sock_conn(verto_ctx *vctx, verto_ev *ev) ret = ENOMEM; goto done; } - conn->gpctx = verto_get_private(ev); + conn->sock_ctx = verto_get_private(ev); conn->us.sd = -1; listen_fd = verto_get_fd(ev); diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c index 8c143e5..0936407 100644 --- a/proxy/src/gssproxy.c +++ b/proxy/src/gssproxy.c @@ -40,9 +40,10 @@ int main(int argc, const char *argv[]) verto_ctx *vctx; verto_ev *ev; int vflags; - int fd; struct gssproxy_ctx *gpctx; + struct gp_sock_ctx *sock_ctx; int ret; + int i; struct poptOption long_options[] = { POPT_AUTOHELP @@ -98,14 +99,6 @@ int main(int argc, const char *argv[]) init_server(gpctx->config->daemonize); - fd = init_unix_socket(gpctx->config->socket_name); - if (fd == -1) { - return 1; - } - - /* special call to tell the Linux kernel gss-proxy is available */ - init_proc_nfsd(gpctx->config); - write_pid(); vctx = init_event_loop(); @@ -114,12 +107,38 @@ int main(int argc, const char *argv[]) } gpctx->vctx = vctx; + /* init main socket */ + sock_ctx = init_unix_socket(gpctx, gpctx->config->socket_name); + if (!sock_ctx) { + return 1; + } + vflags = VERTO_EV_FLAG_PERSIST | VERTO_EV_FLAG_IO_READ; - ev = verto_add_io(vctx, vflags, accept_sock_conn, fd); + ev = verto_add_io(vctx, vflags, accept_sock_conn, sock_ctx->fd); if (!ev) { return 1; } - verto_set_private(ev, gpctx, NULL); + verto_set_private(ev, sock_ctx, NULL); + + /* init secondary sockets */ + for (i = 0; i < gpctx->config->num_svcs; i++) { + if (gpctx->config->svcs[i]->socket != NULL) { + sock_ctx = init_unix_socket(gpctx, gpctx->config->svcs[i]->socket); + if (!sock_ctx) { + return 1; + } + + vflags = VERTO_EV_FLAG_PERSIST | VERTO_EV_FLAG_IO_READ; + ev = verto_add_io(vctx, vflags, accept_sock_conn, sock_ctx->fd); + if (!ev) { + return 1; + } + verto_set_private(ev, sock_ctx, NULL); + } + } + + /* special call to tell the Linux kernel gss-proxy is available */ + init_proc_nfsd(gpctx->config); ret = gp_workers_init(gpctx); if (ret) { -- cgit