Skip to content

Commit f8f308f

Browse files
committed
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>
1 parent 912738e commit f8f308f

File tree

3 files changed

+123
-7
lines changed

3 files changed

+123
-7
lines changed

src/environ.c

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,18 +243,44 @@ static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc)
243243
}
244244
}
245245

246-
static void mag_set_KRB5CCNAME(request_rec *req, const char *dir,
246+
static void mag_set_KRB5CCNAME(request_rec *req, struct mag_config *cfg,
247247
const char *ccname)
248248
{
249249
apr_status_t status;
250-
apr_finfo_t finfo;
250+
apr_int32_t wanted = APR_FINFO_MIN | APR_FINFO_OWNER | APR_FINFO_PROT;
251+
apr_finfo_t finfo = { 0 };
251252
char *path;
252253
char *value;
253254

254-
path = apr_psprintf(req->pool, "%s/%s", dir, ccname);
255-
256-
status = apr_stat(&finfo, path, APR_FINFO_MIN, req->pool);
257-
if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
255+
path = apr_psprintf(req->pool, "%s/%s", cfg->deleg_ccache_dir, ccname);
256+
257+
status = apr_stat(&finfo, path, wanted, req->pool);
258+
if (status == APR_SUCCESS) {
259+
if ((cfg->deleg_ccache_mode != 0) &&
260+
(finfo.protection != cfg->deleg_ccache_mode)) {
261+
status = apr_file_perms_set(path, cfg->deleg_ccache_mode);
262+
if (status != APR_SUCCESS)
263+
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
264+
"failed to set perms (%o) on file (%s)!",
265+
cfg->deleg_ccache_mode, path);
266+
}
267+
if ((cfg->deleg_ccache_uid != 0) &&
268+
(finfo.user != cfg->deleg_ccache_uid)) {
269+
status = lchown(path, cfg->deleg_ccache_uid, -1);
270+
if (status != 0)
271+
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
272+
"failed to set user (%u) on file (%s)!",
273+
cfg->deleg_ccache_uid, path);
274+
}
275+
if ((cfg->deleg_ccache_gid != 0) &&
276+
(finfo.group != cfg->deleg_ccache_gid)) {
277+
status = lchown(path, -1, cfg->deleg_ccache_gid);
278+
if (status != 0)
279+
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
280+
"failed to set group (%u) on file (%s)!",
281+
cfg->deleg_ccache_gid, path);
282+
}
283+
} else {
258284
/* set the file cache anyway, but warn */
259285
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
260286
"KRB5CCNAME file (%s) lookup failed!", path);
@@ -282,7 +308,7 @@ void mag_set_req_data(request_rec *req,
282308

283309
#ifdef HAVE_CRED_STORE
284310
if (cfg->deleg_ccache_dir && mc->delegated && mc->ccname) {
285-
mag_set_KRB5CCNAME(req, cfg->deleg_ccache_dir, mc->ccname);
311+
mag_set_KRB5CCNAME(req, cfg, mc->ccname);
286312
}
287313
#endif
288314
}

src/mod_auth_gssapi.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,87 @@ static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
13321332

13331333
return NULL;
13341334
}
1335+
1336+
#define CCMODE "mode:"
1337+
#define CCUID "uid:"
1338+
#define CCGID "gid:"
1339+
#define NSS_BUF_LEN 2048 /* just use a uid/gid number if not big enough */
1340+
static const char *mag_deleg_ccache_perms(cmd_parms *parms, void *mconfig,
1341+
const char *w)
1342+
{
1343+
struct mag_config *cfg = (struct mag_config *)mconfig;
1344+
1345+
if (strncmp(w, CCMODE, sizeof(CCMODE) - 1) == 0) {
1346+
const char *p = w + sizeof(CCMODE) -1;
1347+
errno = 0;
1348+
/* mode is traditionally represented in octal, but the actual
1349+
* permission bit are using the 3 least significant bit of each quartet
1350+
* so effectively if we read an octal number as hex we get the correct
1351+
* mode bits */
1352+
cfg->deleg_ccache_mode = strtol(p, NULL, 16);
1353+
if (errno != 0) {
1354+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
1355+
"Invalid GssapiDelegCcachePerms mode value [%s]", p);
1356+
/* reset to the default */
1357+
cfg->deleg_ccache_mode = 0;
1358+
}
1359+
} else if (strncmp(w, CCUID, sizeof(CCUID) - 1) == 0) {
1360+
const char *p = w + sizeof(CCUID) - 1;
1361+
errno = 0;
1362+
if (isdigit(*p)) {
1363+
char *endptr;
1364+
cfg->deleg_ccache_uid = strtol(p, &endptr, 0);
1365+
if (errno != 0 || endptr != '\0') {
1366+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
1367+
"Invalid GssapiDelegCcachePerms uid value [%s]",
1368+
p);
1369+
/* reset to the default */
1370+
cfg->deleg_ccache_uid = 0;
1371+
}
1372+
} else {
1373+
struct passwd pwd, *user;
1374+
char buf[NSS_BUF_LEN];
1375+
int ret = getpwnam_r(p, &pwd, buf, NSS_BUF_LEN, &user);
1376+
if ((ret != 0) || user != &pwd) {
1377+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
1378+
"Invalid GssapiDelegCcachePerms uid value [%s]",
1379+
p);
1380+
} else {
1381+
cfg->deleg_ccache_uid = user->pw_uid;
1382+
}
1383+
}
1384+
} else if (strncmp(w, CCGID, sizeof(CCGID) - 1) == 0) {
1385+
const char *p = w + sizeof(CCGID) - 1;
1386+
errno = 0;
1387+
if (isdigit(*p)) {
1388+
char *endptr;
1389+
cfg->deleg_ccache_gid = strtol(p, &endptr, 0);
1390+
if (errno != 0 || endptr != '\0') {
1391+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
1392+
"Invalid GssapiDelegCcachePerms gid value [%s]",
1393+
p);
1394+
/* reset to the default */
1395+
cfg->deleg_ccache_gid = 0;
1396+
}
1397+
} else {
1398+
struct group grp, *group;
1399+
char buf[NSS_BUF_LEN];
1400+
int ret = getgrnam_r(p, &grp, buf, NSS_BUF_LEN, &group);
1401+
if ((ret != 0) || group != &grp) {
1402+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
1403+
"Invalid GssapiDelegCcachePerms gid value [%s]",
1404+
p);
1405+
} else {
1406+
cfg->deleg_ccache_gid = group->gr_gid;
1407+
}
1408+
}
1409+
} else {
1410+
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
1411+
"Invalid GssapiDelegCcachePerms directive [%s]", w);
1412+
}
1413+
1414+
return NULL;
1415+
}
13351416
#endif
13361417

13371418
#ifdef HAVE_GSS_ACQUIRE_CRED_WITH_PASSWORD
@@ -1541,6 +1622,8 @@ static const command_rec mag_commands[] = {
15411622
"Credential Store"),
15421623
AP_INIT_RAW_ARGS("GssapiDelegCcacheDir", mag_deleg_ccache_dir, NULL,
15431624
OR_AUTHCFG, "Directory to store delegated credentials"),
1625+
AP_INIT_ITERATE("GssapiDelegCcachePerms", mag_deleg_ccache_perms, NULL,
1626+
OR_AUTHCFG, "Permissions to assign to Ccache files"),
15441627
AP_INIT_FLAG("GssapiDelegCcacheUnique", mag_deleg_ccache_unique, NULL,
15451628
OR_AUTHCFG, "Use unique ccaches for delgation"),
15461629
AP_INIT_FLAG("GssapiImpersonate", ap_set_flag_slot,

src/mod_auth_gssapi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
# include <gssapi/gssapi_ntlmssp.h>
3737
#endif
3838

39+
#include <ctype.h>
40+
#include <pwd.h>
41+
#include <grp.h>
42+
3943
#include "crypto.h"
4044
#include "sessions.h"
4145
#include "environ.h"
@@ -69,6 +73,9 @@ struct mag_config {
6973
#ifdef HAVE_CRED_STORE
7074
bool use_s4u2proxy;
7175
char *deleg_ccache_dir;
76+
mode_t deleg_ccache_mode;
77+
uid_t deleg_ccache_uid;
78+
gid_t deleg_ccache_gid;
7279
gss_key_value_set_desc *cred_store;
7380
bool deleg_ccache_unique;;
7481
bool s4u2self;

0 commit comments

Comments
 (0)