diff options
-rw-r--r-- | src/environ.c | 40 | ||||
-rw-r--r-- | src/mod_auth_gssapi.c | 83 | ||||
-rw-r--r-- | src/mod_auth_gssapi.h | 7 |
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; |