diff --git a/docs/README.md b/docs/README.md index 63471b250..b6deec157 100644 --- a/docs/README.md +++ b/docs/README.md @@ -127,6 +127,25 @@ To configure the client, we need to set another environment variable: `GSSPROXY_SOCKET`. So, we set that in the same way we set `GSS_USE_PROXY` (i.e., `GSSPROXY_SOCKET=/var/lib/gssproxy/my_app.sock`), and launch. +## Clients running in AT_SECURE context + +When a client application is running in a secure execution context (e.g., setuid/setgid programs where `getauxval(AT_SECURE)` returns non-zero), standard environment variables such as `GSSPROXY_SOCKET` are ignored by the gssproxy client to prevent security issues. + +In this case, the gssproxy client automatically constructs the socket name based on the default socket and the program name. For instance, if the program is called `my_app`, the client will try to connect to a socket named `/var/lib/gssproxy/default.sock.my_app` (assuming the default socket path is `/var/lib/gssproxy/default.sock`). + +To provide access to these clients, you can configure your gssproxy service to listen on this specific socket. In your configuration file, add or modify the `socket` directive: + +```INI +[service/my_app] + mechs = krb5 + cred_store = keytab:/etc/path/to.keytab + euid = appuser + program = /usr/local/bin/my_app + socket = /var/lib/gssproxy/default.sock.my_app +``` + +Then reload the gssproxy configuration: `systemctl try-reload-or-restart gssproxy`. This ensures that even in an `AT_SECURE` context, the application can securely communicate with gssproxy using the expected socket. + ## How to know it's working By far the easiest way to tell is to have a configuration working *without* diff --git a/src/client/gpm_common.c b/src/client/gpm_common.c index 2c0925d05..928b9c187 100644 --- a/src/client/gpm_common.c +++ b/src/client/gpm_common.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -64,17 +65,51 @@ static void gpm_init_once(void) gpm_display_status_init_once(); } +static int get_program_name(char *name, size_t size) +{ + ssize_t ret; + char *p; + + ret = readlink("/proc/self/exe", name, size - 1); + if (ret == -1) { + return errno; + } + name[ret] = '\0'; + + p = strrchr(name, '/'); + if (p) { + p++; + memmove(name, p, ret + 1 - (p - name)); + } + + return 0; +} + static int get_pipe_name(char *name) { const char *socket; - int ret; + unsigned long auxval; + int ret = 1; - socket = gp_getenv("GSSPROXY_SOCKET"); - if (!socket) { - socket = GP_SOCKET_NAME; - } + /* check if this is a "secure" client */ + auxval = getauxval(AT_SECURE); - ret = snprintf(name, PATH_MAX, "%s", socket); + if (auxval == 0) { + /* default case */ + socket = gp_getenv("GSSPROXY_SOCKET"); + if (!socket) { + socket = GP_SOCKET_NAME; + } + + ret = snprintf(name, PATH_MAX, "%s", socket); + } else { + char proc[PATH_MAX]; + ret = get_program_name(proc, sizeof(proc)); + if (ret) { + return ret; + } + ret = snprintf(name, PATH_MAX, "%s.%s", GP_SOCKET_NAME, proc); + } if (ret < 0 || ret >= PATH_MAX) { return ENAMETOOLONG; } @@ -670,6 +705,24 @@ struct gpm_rpc_fn_set { } }; +int gpm_sock_check(void) +{ + struct gpm_ctx *gpmctx; + int ret; + + gpmctx = gpm_get_ctx(); + if (!gpmctx) { + return EFAULT; + } + + ret = gpm_grab_sock(gpmctx); + if (ret == 0) { + gpm_release_sock(gpmctx); + } + + return ret; +} + int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) { struct gpm_ctx *gpmctx; diff --git a/src/client/gssapi_gpm.h b/src/client/gssapi_gpm.h index 164e85e2e..4f6d48df2 100644 --- a/src/client/gssapi_gpm.h +++ b/src/client/gssapi_gpm.h @@ -16,6 +16,7 @@ #include "src/gp_common.h" #include "src/gp_conv.h" +int gpm_sock_check(void); int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res); void gpm_free_xdrs(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res); diff --git a/src/mechglue/gss_plugin.c b/src/mechglue/gss_plugin.c index c7982d1f8..0e423dd44 100644 --- a/src/mechglue/gss_plugin.c +++ b/src/mechglue/gss_plugin.c @@ -2,6 +2,7 @@ #include "gss_plugin.h" #include +#include #include #include @@ -76,8 +77,22 @@ const gss_OID_desc gssproxy_mech_interposer = { static bool enabled(void) { char *envval; + unsigned long auxval; bool ret = GSS_ALWAYS_INTERPOSE; + /* check if this is a "secure" client */ + auxval = getauxval(AT_SECURE); + + /* in "secure" clients gp_getenv(0 always fails (it uses secure_getenv), + * therefore for "secure" clients we check if we can access the per + * client secure socket if available */ + if (auxval != 0) { + int check = gpm_sock_check(); + if (check == 0) { + return true; + } + } + /* avoid looping in the gssproxy daemon by avoiding to interpose * any mechanism */ envval = gp_getenv("GSS_USE_PROXY");