summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;