summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-11-02 06:34:11 -0400
committerSimo Sorce <simo@redhat.com>2016-11-30 05:39:33 -0500
commitf8f308f00b7f2695ae811d64038febc59dc688d5 (patch)
tree45637d245ab69574518a697759562161b9592479
parent912738edbf248c9d9c2960cd4ff1daaa855e6c7e (diff)
downloadmod_auth_gssapi-f8f308f00b7f2695ae811d64038febc59dc688d5.tar.gz
mod_auth_gssapi-f8f308f00b7f2695ae811d64038febc59dc688d5.tar.xz
mod_auth_gssapi-f8f308f00b7f2695ae811d64038febc59dc688d5.zip
Add option to set custom permissions on ccache
This allows apache to set permission so that another user in the default group can access the ccache. Useful when apache passes the request to a process running under a different user or group id number. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Robbie Harwood <rharwood@redhat.com>
-rw-r--r--src/environ.c40
-rw-r--r--src/mod_auth_gssapi.c83
-rw-r--r--src/mod_auth_gssapi.h7
3 files changed, 123 insertions, 7 deletions
diff --git a/src/environ.c b/src/environ.c
index 8fefb8e..7b8a54b 100644
--- a/src/environ.c
+++ b/src/environ.c
@@ -243,18 +243,44 @@ static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc)
}
}
-static void mag_set_KRB5CCNAME(request_rec *req, const char *dir,
+static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg,
const char *ccname)
{
apr_status_t status;
- apr_finfo_t finfo;
+ apr_int32_t wanted = APR_FINFO_MIN | APR_FINFO_OWNER | APR_FINFO_PROT;
+ apr_finfo_t finfo = { 0 };
char *path;
char *value;
- path = apr_psprintf(req->pool, "%s/%s", dir, ccname);
-
- status = apr_stat(&finfo, path, APR_FINFO_MIN, req->pool);
- if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
+ path = apr_psprintf(req->pool, "%s/%s", cfg->deleg_ccache_dir, ccname);
+
+ status = apr_stat(&finfo, path, wanted, req->pool);
+ if (status == APR_SUCCESS) {
+ if ((cfg->deleg_ccache_mode != 0) &&
+ (finfo.protection != cfg->deleg_ccache_mode)) {
+ status = apr_file_perms_set(path, cfg->deleg_ccache_mode);
+ if (status != APR_SUCCESS)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
+ "failed to set perms (%o) on file (%s)!",
+ cfg->deleg_ccache_mode, path);
+ }
+ if ((cfg->deleg_ccache_uid != 0) &&
+ (finfo.user != cfg->deleg_ccache_uid)) {
+ status = lchown(path, cfg->deleg_ccache_uid, -1);
+ if (status != 0)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
+ "failed to set user (%u) on file (%s)!",
+ cfg->deleg_ccache_uid, path);
+ }
+ if ((cfg->deleg_ccache_gid != 0) &&
+ (finfo.group != cfg->deleg_ccache_gid)) {
+ status = lchown(path, -1, cfg->deleg_ccache_gid);
+ if (status != 0)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
+ "failed to set group (%u) on file (%s)!",
+ cfg->deleg_ccache_gid, path);
+ }
+ } else {
/* set the file cache anyway, but warn */
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
"KRB5CCNAME file (%s) lookup failed!", path);
@@ -282,7 +308,7 @@ void mag_set_req_data(request_rec *req,
#ifdef HAVE_CRED_STORE
if (cfg->deleg_ccache_dir && mc->delegated && mc->ccname) {
- mag_set_KRB5CCNAME(req, cfg->deleg_ccache_dir, mc->ccname);
+ mag_set_KRB5CCNAME(req, cfg, mc->ccname);
}
#endif
}
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index 9f24401..c3f258b 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -1332,6 +1332,87 @@ static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
return NULL;
}
+
+#define CCMODE "mode:"
+#define CCUID "uid:"
+#define CCGID "gid:"
+#define NSS_BUF_LEN 2048 /* just use a uid/gid number if not big enough */
+static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
+ const char *w)
+{
+ struct mag_config *cfg = (struct mag_config *)mconfig;
+
+ if (strncmp(w, CCMODE, sizeof(CCMODE) - 1) == 0) {
+ const char *p = w + sizeof(CCMODE) -1;
+ errno = 0;
+ /* mode is traditionally represented in octal, but the actual
+ * permission bit are using the 3 least significant bit of each quartet
+ * so effectively if we read an octal number as hex we get the correct
+ * mode bits */
+ cfg->deleg_ccache_mode = strtol(p, NULL, 16);
+ if (errno != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
+ "Invalid GssapiDelegCcachePerms mode value [%s]", p);
+ /* reset to the default */
+ cfg->deleg_ccache_mode = 0;
+ }
+ } else if (strncmp(w, CCUID, sizeof(CCUID) - 1) == 0) {
+ const char *p = w + sizeof(CCUID) - 1;
+ errno = 0;
+ if (isdigit(*p)) {
+ char *endptr;
+ cfg->deleg_ccache_uid = strtol(p, &endptr, 0);
+ if (errno != 0 || endptr != '\0') {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
+ "Invalid GssapiDelegCcachePerms uid value [%s]",
+ p);
+ /* reset to the default */
+ cfg->deleg_ccache_uid = 0;
+ }
+ } else {
+ struct passwd pwd, *user;
+ char buf[NSS_BUF_LEN];
+ int ret = getpwnam_r(p, &pwd, buf, NSS_BUF_LEN, &user);
+ if ((ret != 0) || user != &pwd) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
+ "Invalid GssapiDelegCcachePerms uid value [%s]",
+ p);
+ } else {
+ cfg->deleg_ccache_uid = user->pw_uid;
+ }
+ }
+ } else if (strncmp(w, CCGID, sizeof(CCGID) - 1) == 0) {
+ const char *p = w + sizeof(CCGID) - 1;
+ errno = 0;
+ if (isdigit(*p)) {
+ char *endptr;
+ cfg->deleg_ccache_gid = strtol(p, &endptr, 0);
+ if (errno != 0 || endptr != '\0') {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
+ "Invalid GssapiDelegCcachePerms gid value [%s]",
+ p);
+ /* reset to the default */
+ cfg->deleg_ccache_gid = 0;
+ }
+ } else {
+ struct group grp, *group;
+ char buf[NSS_BUF_LEN];
+ int ret = getgrnam_r(p, &grp, buf, NSS_BUF_LEN, &group);
+ if ((ret != 0) || group != &grp) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
+ "Invalid GssapiDelegCcachePerms gid value [%s]",
+ p);
+ } else {
+ cfg->deleg_ccache_gid = group->gr_gid;
+ }
+ }
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
+ "Invalid GssapiDelegCcachePerms directive [%s]", w);
+ }
+
+ return NULL;
+}
#endif
#ifdef HAVE_GSS_ACQUIRE_CRED_WITH_PASSWORD
@@ -1541,6 +1622,8 @@ static const command_rec mag_commands[] = {
"Credential Store"),
AP_INIT_RAW_ARGS("GssapiDelegCcacheDir", mag_deleg_ccache_dir, NULL,
OR_AUTHCFG, "Directory to store delegated credentials"),
+ AP_INIT_ITERATE("GssapiDelegCcachePerms", mag_deleg_ccache_perms, NULL,
+ OR_AUTHCFG, "Permissions to assign to Ccache files"),
AP_INIT_FLAG("GssapiDelegCcacheUnique", mag_deleg_ccache_unique, NULL,
OR_AUTHCFG, "Use unique ccaches for delgation"),
AP_INIT_FLAG("GssapiImpersonate", ap_set_flag_slot,
diff --git a/src/mod_auth_gssapi.h b/src/mod_auth_gssapi.h
index 6ff9fbd..1a5ff8b 100644
--- a/src/mod_auth_gssapi.h
+++ b/src/mod_auth_gssapi.h
@@ -36,6 +36,10 @@
# include <gssapi/gssapi_ntlmssp.h>
#endif
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+
#include "crypto.h"
#include "sessions.h"
#include "environ.h"
@@ -69,6 +73,9 @@ struct mag_config {
#ifdef HAVE_CRED_STORE
bool use_s4u2proxy;
char *deleg_ccache_dir;
+ mode_t deleg_ccache_mode;
+ uid_t deleg_ccache_uid;
+ gid_t deleg_ccache_gid;
gss_key_value_set_desc *cred_store;
bool deleg_ccache_unique;;
bool s4u2self;