259 lines
8.5 KiB
C
259 lines
8.5 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2009, 2012 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
#include "eintr_wrappers.h"
|
|
#include "gtm_string.h"
|
|
#include "gtm_stdio.h"
|
|
#include "gtm_stdlib.h"
|
|
#include "gtm_limits.h"
|
|
#include "gtm_unistd.h"
|
|
#include "gtm_fcntl.h"
|
|
#include "gtm_stat.h"
|
|
#include "gtm_pwd.h"
|
|
#include <grp.h>
|
|
#include "gtm_permissions.h"
|
|
#include "send_msg.h"
|
|
|
|
#if defined(__hpux) && defined(__hppa)
|
|
# define LIBGTMSHR "%s/libgtmshr.sl"
|
|
#elif defined(__MVS__)
|
|
# define LIBGTMSHR "%s/libgtmshr.dll"
|
|
#else
|
|
# define LIBGTMSHR "%s/libgtmshr.so"
|
|
#endif
|
|
/* Return the group id of the distribution based on libgtmshr.xx[x]. If there is some
|
|
problem accessing that file then return -1 which signals no change to group. Otherwise,
|
|
the pointer to the stat buffer will contain the result of the call to STAT_FILE */
|
|
int gtm_get_group_id(struct stat *stat_buff)
|
|
{
|
|
char *env_var;
|
|
int ret_stat;
|
|
char temp[PATH_MAX + SIZEOF("libgtmshr.dll")];
|
|
|
|
env_var = GETENV("gtm_dist");
|
|
if (NULL != env_var)
|
|
{
|
|
/* build a path to libgtmshr.so or .sl on hpux or .dll on zos */
|
|
SNPRINTF(temp, SIZEOF(temp), LIBGTMSHR, env_var);
|
|
STAT_FILE(temp, stat_buff, ret_stat);
|
|
if (0 == ret_stat)
|
|
return(stat_buff->st_gid);
|
|
}
|
|
/* return a -1 if $gtm_dist found or if STAT_FILE returned a -1 */
|
|
return(-1);
|
|
}
|
|
|
|
/* Return TRUE is the "uid" parameter is a member of the "gid" group parameter.
|
|
Return FALSE if it is not. */
|
|
int gtm_member_group_id(int uid, int gid)
|
|
{
|
|
struct group *grp;
|
|
struct passwd *pwd, *pwd2;
|
|
|
|
/* check effective group if current effective uid */
|
|
if ((GETEUID() == uid) && (GETEGID() == gid))
|
|
return(TRUE);
|
|
/* get group id for database */
|
|
grp = getgrgid(gid);
|
|
if (NULL == grp)
|
|
return(FALSE); /* if group id not found then assume uid not a member */
|
|
pwd = getpwuid(uid);
|
|
if (NULL == pwd)
|
|
return(FALSE); /* if user id not found then assume uid not a member */
|
|
/* if the gid of the file is the same as the gid for the process uid we are done */
|
|
if (gid == pwd->pw_gid)
|
|
return(TRUE);
|
|
else
|
|
{
|
|
/*
|
|
* Otherwise we have to compare the name stored in pwd struct
|
|
* with the names of the group members in the group struct.
|
|
*/
|
|
while (NULL != *(grp->gr_mem))
|
|
{
|
|
if (!strcmp(pwd->pw_name, *(grp->gr_mem++)))
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
/* Based on security rules in this routine, set *group_id of the group to be used
|
|
for shared resources, journals, and temp files. If a no change then it will be set to -1.
|
|
Also, set *perm to the permissions to be used. The precalculated world_write_perm (need to
|
|
change name to masked_permissions) is to be used in the one case indicated below.
|
|
|
|
Populates pdd struct and returns negative value for error, returns non-negative for success. */
|
|
int gtm_set_group_and_perm(struct stat *stat_buff, int *group_id, int *perm, enum perm_target_types target_type,
|
|
struct perm_diag_data *pdd)
|
|
{
|
|
int lib_gid = -1;
|
|
int use_world_writeable;
|
|
uid_t process_uid;
|
|
gid_t process_gid;
|
|
uid_t db_uid;
|
|
struct stat dist_stat_buff;
|
|
int opener_is_file_owner;
|
|
int opener_is_root;
|
|
int opener_in_file_group;
|
|
int owner_in_file_group;
|
|
int gtm_group_restricted;
|
|
|
|
/* get process_uid/gid */
|
|
process_uid = GETEUID();
|
|
process_gid = GETEGID();
|
|
/* get database uid */
|
|
db_uid = stat_buff->st_uid;
|
|
/* set variables for permission logic */
|
|
opener_is_file_owner = (process_uid == db_uid);
|
|
opener_is_root = (process_uid == 0);
|
|
opener_in_file_group = gtm_member_group_id(process_uid, stat_buff->st_gid);
|
|
owner_in_file_group = gtm_member_group_id(db_uid, stat_buff->st_gid);
|
|
/* find restricted group, if any */
|
|
lib_gid = gtm_get_group_id(&dist_stat_buff);
|
|
gtm_group_restricted = (lib_gid != -1) && !(dist_stat_buff.st_mode & 01); /* not world executable */
|
|
|
|
/* set default gid */
|
|
#ifdef __osf__
|
|
*group_id = process_gid;
|
|
#else
|
|
*group_id = -1;
|
|
#endif
|
|
/* set no permissions as a default in case none of our conditions match */
|
|
*perm = 0;
|
|
|
|
if (0006 & stat_buff->st_mode)
|
|
{
|
|
/* file is accessible to other */
|
|
if (opener_in_file_group) /* otherwise, use default gid */
|
|
*group_id = stat_buff->st_gid;
|
|
if (PERM_FILE == target_type)
|
|
*perm = (!opener_in_file_group && (0020 & stat_buff->st_mode)) ? 0666 : (stat_buff->st_mode & 0666);
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0666;
|
|
else
|
|
assertpro(FALSE);
|
|
} else if (0600 & stat_buff->st_mode && !(0066 & stat_buff->st_mode))
|
|
{
|
|
/* file is only user accessible */
|
|
/* use default group */
|
|
assert(opener_is_file_owner || opener_is_root);
|
|
if (PERM_FILE == target_type)
|
|
*perm = 0600; /* read write for user */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0600; /* read write for user */
|
|
else
|
|
assertpro(FALSE);
|
|
} else if (0060 & stat_buff->st_mode && !(0606 & stat_buff->st_mode))
|
|
{
|
|
/* file is only group accessible */
|
|
*group_id = stat_buff->st_gid; /* use file group */
|
|
assert(opener_in_file_group || opener_is_root);
|
|
if (PERM_FILE == target_type)
|
|
*perm = stat_buff->st_mode & 0060; /* use file permissions, masked for group read/write */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0660; /* read/write for group - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
} else
|
|
{
|
|
/* file is accessible to user and group */
|
|
if (opener_is_file_owner && opener_in_file_group)
|
|
{
|
|
*group_id = stat_buff->st_gid; /* use file group */
|
|
if (PERM_FILE == target_type)
|
|
*perm = stat_buff->st_mode & 0660; /* use file permissions, masked for user/group read/write */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0660; /* read/write for user/group - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
} else
|
|
{
|
|
if (opener_is_file_owner && !opener_in_file_group)
|
|
{
|
|
if (gtm_group_restricted)
|
|
{
|
|
*group_id = lib_gid; /* use restricted group */
|
|
assert(gtm_member_group_id(process_uid, *group_id) || opener_is_root);
|
|
if (PERM_FILE == target_type)
|
|
*perm = 0660; /* user/group read/write */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0660; /* read/write for user/group - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
} else
|
|
{
|
|
/* use default group */
|
|
if (PERM_FILE == target_type)
|
|
*perm = 0666; /* read/write for all */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0666; /* read/write for all - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
}
|
|
} else if (!opener_is_file_owner && opener_in_file_group || opener_is_root)
|
|
{
|
|
/* opener has access either via file group membership or because he is root */
|
|
if (owner_in_file_group)
|
|
{
|
|
*group_id = stat_buff->st_gid; /* use file group */
|
|
if (PERM_FILE == target_type)
|
|
*perm = stat_buff->st_mode & 0660; /* use masked file permissions */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0660; /* read/write for user/group - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
|
|
} else if (gtm_group_restricted)
|
|
{
|
|
*group_id = lib_gid; /* use restricted group */
|
|
assert(gtm_member_group_id(process_uid, *group_id) || opener_is_root);
|
|
if (PERM_FILE == target_type)
|
|
*perm = 0660; /* user/group read/write */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0660; /* read/write for user/group - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
} else
|
|
{
|
|
*group_id = stat_buff->st_gid; /* use file group */
|
|
if (PERM_FILE == target_type)
|
|
*perm = 0666; /* read/write for all - ensure file owner read/write access */
|
|
else if (PERM_IPC == target_type)
|
|
*perm = 0666; /* read/write for all - all readers need write for ipc */
|
|
else
|
|
assertpro(FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if we never set *perm, return error value */
|
|
if (*perm == 0)
|
|
{
|
|
/* populate perm diag data */
|
|
pdd->process_uid = process_uid;
|
|
pdd->process_gid = process_gid;
|
|
pdd->file_uid = stat_buff->st_uid;
|
|
pdd->file_gid = stat_buff->st_gid;
|
|
SNPRINTF(pdd->file_perm, SIZEOF(pdd->file_perm), "%04o", stat_buff->st_mode & 07777);
|
|
pdd->lib_gid = dist_stat_buff.st_gid;
|
|
SNPRINTF(pdd->lib_perm, SIZEOF(pdd->lib_perm), "%04o", dist_stat_buff.st_mode & 07777);
|
|
pdd->opener_in_file_group = opener_in_file_group;
|
|
pdd->owner_in_file_group = owner_in_file_group;
|
|
|
|
return -1;
|
|
} else
|
|
return 0;
|
|
}
|