259 lines
8.6 KiB
C
259 lines
8.6 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2008, 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"
|
|
#define BYPASS_MEMCPY_OVERRIDE /* Signals gtm_string.h to not override memcpy(). This causes linking problems when libmumps.a
|
|
* is not available.
|
|
*/
|
|
#/* We want system malloc, not gtm_malloc (which comes from mdef.h --> mdefsp.h). Since gtmsecshr_wrapper runs as root,
|
|
* using the system malloc will increase security over using gtm_malloc. Additionally, by not using gtm_malloc, we
|
|
* are reducing code bloat.
|
|
*/
|
|
#undef malloc
|
|
#undef free
|
|
#include "gtm_unistd.h"
|
|
#include "gtm_stat.h"
|
|
#include "gtm_stdlib.h"
|
|
#include "gtm_stdio.h"
|
|
#include "gtm_string.h"
|
|
#include "gtm_syslog.h"
|
|
#include "main_pragma.h"
|
|
#ifndef __MVS__
|
|
# include <malloc.h>
|
|
#endif
|
|
#include <errno.h>
|
|
#define ROOTUID 0
|
|
#define ROOTGID 0
|
|
#define MAX_ENV_VAR_VAL_LEN 1024
|
|
#define MAX_ALLOWABLE_LEN 256
|
|
#define OVERWRITE 1
|
|
#define GTM_TMP "gtm_tmp"
|
|
#define GTM_DIST "gtm_dist"
|
|
#define GTM_DBGLVL "gtmdbglvl"
|
|
#ifdef __MVS__
|
|
# define GTM_ZOS_AUTOCVT "_BPXK_AUTOCVT"
|
|
# define GTM_ZOS_AUTOCVT_ON "ON"
|
|
#endif
|
|
#define SUB_PATH_TO_GTMSECSHRDIR "/gtmsecshrdir"
|
|
#define REL_PATH_TO_CURDIR "."
|
|
#define REL_PATH_TO_GTMSECSHR "./gtmsecshr"
|
|
#define GTMSECSHR_BASENAME "/gtmsecshr"
|
|
#define MAX_ENV_NAME_LEN 2048
|
|
|
|
#ifdef __osf__
|
|
/* On OSF/1 (Digital Unix), pointers are 64 bits wide; the only exception to this is C programs for which one may
|
|
* specify compiler and link editor options in order to use (and allocate) 32-bit pointers. However, since C is
|
|
* the only exception and, in particular because the operating system does not support such an exception, the argv
|
|
* array passed to the main program is an array of 64-bit pointers. Thus the C program needs to declare argv[]
|
|
* as an array of 64-bit pointers and needs to do the same for any pointer it sets to an element of argv[].
|
|
*/
|
|
#pragma pointer_size (save)
|
|
#pragma pointer_size (long)
|
|
#endif
|
|
|
|
typedef char **environptr_t;
|
|
extern char **environ;
|
|
|
|
#ifdef __osf__
|
|
#pragma pointer_size (restore)
|
|
#endif
|
|
|
|
int gtm_setenv(char * env_var_name, char * env_var_val, int overwrite);
|
|
int gtm_setenv(char * env_var_name, char * env_var_val, int overwrite)
|
|
{ /* The overwrite parameter is not used. In our case we always want to set the value */
|
|
char *env_var_ptr;
|
|
int len;
|
|
|
|
len = STRLEN(env_var_name) + STRLEN("=") + STRLEN(env_var_val) + 1;
|
|
env_var_ptr = (char *)malloc(len);
|
|
if (NULL == env_var_ptr)
|
|
return -1;
|
|
strcpy(env_var_ptr, env_var_name);
|
|
strcat(env_var_ptr, "=");
|
|
strcat(env_var_ptr, env_var_val);
|
|
if (putenv(env_var_ptr))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
int gtm_unsetenv(char * env_var_name);
|
|
int gtm_unsetenv(char * env_var_name)
|
|
{
|
|
return gtm_setenv(env_var_name, "", OVERWRITE);
|
|
}
|
|
|
|
int gtm_clearenv(void);
|
|
int gtm_clearenv()
|
|
{
|
|
char env_var_name[MAX_ENV_NAME_LEN];
|
|
environptr_t p;
|
|
char *eq;
|
|
int len;
|
|
|
|
if (NULL == environ)
|
|
return 0;
|
|
for (p = environ; *p; p++)
|
|
{
|
|
eq = strchr(*p, '=');
|
|
if (NULL != eq)
|
|
{
|
|
len = (int)(eq - *p);
|
|
if (MAX_ENV_NAME_LEN > len)
|
|
{
|
|
memcpy(env_var_name, *p, len);
|
|
env_var_name[len] = '\0';
|
|
if (gtm_unsetenv(env_var_name))
|
|
return -1;
|
|
} else
|
|
return -1;
|
|
} else
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int ret, status;
|
|
char *env_var_ptr;
|
|
struct stat gtm_secshrdir_stat;
|
|
struct stat gtm_secshr_stat;
|
|
char gtm_dist_val[MAX_ENV_VAR_VAL_LEN];
|
|
char gtm_tmp_val[MAX_ENV_VAR_VAL_LEN];
|
|
char gtm_dbglvl_val[MAX_ENV_VAR_VAL_LEN];
|
|
char gtm_secshrdir_path[MAX_ENV_VAR_VAL_LEN];
|
|
char gtm_secshr_path[MAX_ENV_VAR_VAL_LEN];
|
|
char gtm_secshr_orig_path[MAX_ENV_VAR_VAL_LEN];
|
|
int gtm_tmp_exists = 0;
|
|
int gtm_dbglvl_exists = 0;
|
|
|
|
OPENLOG("GTMSECSHRINIT", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_USER);
|
|
ret = 0; /* start positive */
|
|
/* get the ones we need */
|
|
if (env_var_ptr = getenv(GTM_DIST)) /* Warning - assignment */
|
|
{
|
|
if (MAX_ALLOWABLE_LEN < strlen(env_var_ptr) + STR_LIT_LEN(SUB_PATH_TO_GTMSECSHRDIR)
|
|
+ STR_LIT_LEN(GTMSECSHR_BASENAME))
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "gtm_dist env var too long. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
} else
|
|
{
|
|
strcpy(gtm_dist_val, env_var_ptr);
|
|
/* point the path to the real gtmsecshr - for display purposes only */
|
|
strcpy(gtm_secshr_path, env_var_ptr);
|
|
strcat(gtm_secshr_path, SUB_PATH_TO_GTMSECSHRDIR);
|
|
strcat(gtm_secshr_path, GTMSECSHR_BASENAME);
|
|
/* point the path to the real gtmsecshrdir */
|
|
strcpy(gtm_secshrdir_path, env_var_ptr);
|
|
strcat(gtm_secshrdir_path, SUB_PATH_TO_GTMSECSHRDIR);
|
|
}
|
|
} else
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "gtm_dist env var does not exist. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
}
|
|
if (env_var_ptr = getenv(GTM_TMP)) /* Warning - assignment */
|
|
{
|
|
if (MAX_ALLOWABLE_LEN < strlen(env_var_ptr))
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "gtm_tmp env var too long. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
} else
|
|
{
|
|
gtm_tmp_exists = 1;
|
|
strcpy(gtm_tmp_val, env_var_ptr);
|
|
}
|
|
}
|
|
if (env_var_ptr = getenv(GTM_DBGLVL)) /* Warning - assignment */
|
|
{
|
|
if (MAX_ALLOWABLE_LEN < strlen(env_var_ptr))
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "gtmdbglvl env var too long. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
} else
|
|
{
|
|
gtm_dbglvl_exists = 1;
|
|
strcpy(gtm_dbglvl_val, env_var_ptr);
|
|
}
|
|
}
|
|
# ifdef __MVS__
|
|
if (!(env_var_ptr = getenv(GTM_ZOS_AUTOCVT))) /* Warning - assignment */
|
|
SYSLOG(LOG_USER | LOG_INFO, "_BPXK_AUTOCVT is not set, forcing autoconversion\n");
|
|
# endif
|
|
if (!ret)
|
|
{ /* clear all */
|
|
status = gtm_clearenv();
|
|
if (status)
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "clearenv failed. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
}
|
|
/* add the ones we need */
|
|
status = gtm_setenv(GTM_DIST, gtm_dist_val, OVERWRITE);
|
|
if (status)
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "setenv for gtm_dist failed. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
}
|
|
if (gtm_tmp_exists)
|
|
{
|
|
status = gtm_setenv(GTM_TMP, gtm_tmp_val, OVERWRITE);
|
|
if (status)
|
|
{
|
|
SYSLOG(LOG_USER | LOG_INFO, "setenv for gtm_tmp failed. gtmsecshr will not be started\n");
|
|
ret = -1;
|
|
}
|
|
}
|
|
# ifdef __MVS__
|
|
status = gtm_setenv(GTM_ZOS_AUTOCVT, GTM_ZOS_AUTOCVT_ON, OVERWRITE);
|
|
if (status)
|
|
SYSLOG(LOG_USER | LOG_INFO,
|
|
"setenv for _BPXK_AUTOCVT failed. gtmsecshr logs may contain mixed ASCII and EBCDIC\n");
|
|
# endif
|
|
}
|
|
if (!ret)
|
|
{ /* go to root */
|
|
if (-1 == CHDIR(gtm_secshrdir_path))
|
|
SYSLOG(LOG_USER | LOG_INFO, "chdir failed on %s, errno %d. gtmsecshr will not be started\n",
|
|
gtm_secshrdir_path, errno);
|
|
else if (-1 == Stat(REL_PATH_TO_CURDIR, >m_secshrdir_stat))
|
|
SYSLOG(LOG_USER | LOG_INFO, "stat failed on %s, errno %d. gtmsecshr will not be started\n",
|
|
gtm_secshrdir_path, errno);
|
|
else if (ROOTUID != gtm_secshrdir_stat.st_uid)
|
|
SYSLOG(LOG_USER | LOG_INFO, "%s not owned by root. gtmsecshr will not be started\n", gtm_secshrdir_path);
|
|
else if (gtm_secshrdir_stat.st_mode & 0277)
|
|
SYSLOG(LOG_USER | LOG_INFO, "%s permissions incorrect (%04o). gtmsecshr will not be started\n",
|
|
gtm_secshrdir_path, gtm_secshrdir_stat.st_mode & 0777);
|
|
else if (-1 == Stat(REL_PATH_TO_GTMSECSHR, >m_secshr_stat))
|
|
SYSLOG(LOG_USER | LOG_INFO, "stat failed on %s, errno %d. gtmsecshr will not be started\n",
|
|
gtm_secshr_path, errno);
|
|
else if (ROOTUID != gtm_secshr_stat.st_uid)
|
|
SYSLOG(LOG_USER | LOG_INFO, "%s not owned by root. gtmsecshr will not be started\n", gtm_secshr_path);
|
|
else if (gtm_secshr_stat.st_mode & 022)
|
|
SYSLOG(LOG_USER | LOG_INFO, "%s writable. gtmsecshr will not be started\n", gtm_secshr_path);
|
|
else if (!(gtm_secshr_stat.st_mode & 04000))
|
|
SYSLOG(LOG_USER | LOG_INFO, "%s not set-uid. gtmsecshr will not be started\n", gtm_secshr_path);
|
|
else if (-1 == setuid(ROOTUID))
|
|
SYSLOG(LOG_USER | LOG_INFO, "setuid failed. gtmsecshr will not be started\n");
|
|
else
|
|
{ /* call the real gtmsecshr, but have ps display the original gtmsecshr location */
|
|
strcpy(gtm_secshr_orig_path, gtm_dist_val);
|
|
strcat(gtm_secshr_orig_path, GTMSECSHR_BASENAME);
|
|
ret = execl(REL_PATH_TO_GTMSECSHR, gtm_secshr_orig_path, NULL);
|
|
if (-1 == ret)
|
|
SYSLOG(LOG_USER | LOG_INFO, "execl of %s failed\n", gtm_secshr_path);
|
|
}
|
|
}
|
|
closelog();
|
|
return ret;
|
|
}
|