This patch fixes insufficient privilege checking for Linux. If linked against
fscaps binaries, the geteuid() != getuid() wont work anymore. Additionally,
some getenv()'s were not guarded by the privilege check which could allow
local users to load drivers for the engine from any directory.
Please review and include. :)
Sebastian
--
~ perl self.pl
~ $_='print"\$_=\47$_\47;eval"';eval
~ [email protected] - SuSE Security Team
---
SUSE LINUX Products GmbH, GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer, HRB
16746 (AG Nürnberg)
Maxfeldstraße 5
90409 Nürnberg
Germany
diff -rupN openssl-1.0.0d/Configure openssl-1.0.0d.fscaps/Configure
--- openssl-1.0.0d/Configure 2010-11-30 23:19:26.000000000 +0100
+++ openssl-1.0.0d.fscaps/Configure 2011-05-17 11:31:03.662732277 +0200
@@ -1353,6 +1353,12 @@ if ($target =~ /^BSD\-/)
$shared_ldflag.=" -Wl,-rpath,\$(LIBRPATH)" if ($prefix !~ m|^/usr[/]*$|);
}
+if ($target =~ /^linux/i) {
+ if (-e "/usr/include/sys/prctl.h") {
+ $cflags .= " -DPRCTL_DUMPABLE";
+ }
+}
+
if ($sys_id ne "")
{
#$cflags="-DOPENSSL_SYSNAME_$sys_id $cflags";
diff -rupN openssl-1.0.0d/crypto/conf/conf_api.c openssl-1.0.0d.fscaps/crypto/conf/conf_api.c
--- openssl-1.0.0d/crypto/conf/conf_api.c 2010-06-15 19:25:07.000000000 +0200
+++ openssl-1.0.0d.fscaps/crypto/conf/conf_api.c 2011-05-17 10:50:41.459733777 +0200
@@ -139,7 +139,7 @@ char *_CONF_get_string(const CONF *conf,
vv.section=(char *)section;
v=lh_CONF_VALUE_retrieve(conf->data,&vv);
if (v != NULL) return(v->value);
- if (strcmp(section,"ENV") == 0)
+ if (!OPENSSL_issetugid() && (strcmp(section,"ENV") == 0))
{
p=getenv(name);
if (p != NULL) return(p);
@@ -154,7 +154,7 @@ char *_CONF_get_string(const CONF *conf,
return(NULL);
}
else
- return(getenv(name));
+ return (OPENSSL_issetugid() ? NULL : getenv(name));
}
#if 0 /* There's no way to provide error checking with this function, so
diff -rupN openssl-1.0.0d/crypto/conf/conf_mod.c openssl-1.0.0d.fscaps/crypto/conf/conf_mod.c
--- openssl-1.0.0d/crypto/conf/conf_mod.c 2008-11-05 19:38:55.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/conf/conf_mod.c 2011-05-17 10:51:56.927608451 +0200
@@ -548,6 +548,9 @@ char *CONF_get1_default_config_file(void
char *file;
int len;
+ if (OPENSSL_issetugid())
+ return NULL;
+
file = getenv("OPENSSL_CONF");
if (file)
return BUF_strdup(file);
diff -rupN openssl-1.0.0d/crypto/engine/eng_list.c openssl-1.0.0d.fscaps/crypto/engine/eng_list.c
--- openssl-1.0.0d/crypto/engine/eng_list.c 2010-03-27 19:28:13.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/engine/eng_list.c 2011-05-17 10:53:29.325608809 +0200
@@ -399,9 +399,9 @@ ENGINE *ENGINE_by_id(const char *id)
if (strcmp(id, "dynamic"))
{
#ifdef OPENSSL_SYS_VMS
- if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]";
+ if(OPENSSL_issetugid() || (load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]";
#else
- if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR;
+ if(OPENSSL_issetugid() || (load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR;
#endif
iterator = ENGINE_by_id("dynamic");
if(!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
diff -rupN openssl-1.0.0d/crypto/uid.c openssl-1.0.0d.fscaps/crypto/uid.c
--- openssl-1.0.0d/crypto/uid.c 2003-11-28 14:10:55.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/uid.c 2011-05-17 11:40:05.791608864 +0200
@@ -77,8 +77,26 @@ int OPENSSL_issetugid(void)
#include OPENSSL_UNISTD
#include <sys/types.h>
+#ifdef LIBC_ENABLE_SECURE
+extern int __libc_enable_secure;
+#endif
+#ifdef PRCTL_DUMPABLE
+#include <sys/prctl.h>
+#endif
+
int OPENSSL_issetugid(void)
{
+#ifdef LIBC_ENABLE_SECURE
+ if (__libc_enable_secure) return 1;
+#endif
+#ifdef PRCTL_DUMPABLE
+ /* 0 -> not dumpable, 2 -> dumpable by root only from
+ * Linux kernel 2.6.13 - 2.6.17, so we require dumpable
+ * flag to be == 1 to accept non-secure mode.
+ */
+ if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) != 1)
+ return 1;
+#endif
if (getuid() != geteuid()) return 1;
if (getgid() != getegid()) return 1;
return 0;
diff -rupN openssl-1.0.0d/crypto/uidtest.c openssl-1.0.0d.fscaps/crypto/uidtest.c
--- openssl-1.0.0d/crypto/uidtest.c 1970-01-01 01:00:00.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/uidtest.c 2011-05-17 12:11:34.212608831 +0200
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+extern int OPENSSL_issetugid(void);
+
+int main()
+{
+ printf("secure mode: %d\n", OPENSSL_issetugid());
+ return OPENSSL_issetugid();
+}
+
diff -rupN openssl-1.0.0d/crypto/x509/by_dir.c openssl-1.0.0d.fscaps/crypto/x509/by_dir.c
--- openssl-1.0.0d/crypto/x509/by_dir.c 2010-02-19 19:26:23.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/x509/by_dir.c 2011-05-17 10:55:09.953608655 +0200
@@ -135,7 +135,8 @@ static int dir_ctrl(X509_LOOKUP *ctx, in
case X509_L_ADD_DIR:
if (argl == X509_FILETYPE_DEFAULT)
{
- dir=(char *)getenv(X509_get_default_cert_dir_env());
+ if (!OPENSSL_issetugid())
+ dir=(char *)getenv(X509_get_default_cert_dir_env());
if (dir)
ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
else
diff -rupN openssl-1.0.0d/crypto/x509/by_file.c openssl-1.0.0d.fscaps/crypto/x509/by_file.c
--- openssl-1.0.0d/crypto/x509/by_file.c 2005-12-18 20:11:37.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/x509/by_file.c 2011-05-17 12:02:53.237608771 +0200
@@ -93,14 +93,15 @@ static int by_file_ctrl(X509_LOOKUP *ctx
char **ret)
{
int ok=0;
- char *file;
+ char *file = NULL;
switch (cmd)
{
case X509_L_FILE_LOAD:
if (argl == X509_FILETYPE_DEFAULT)
{
- file = (char *)getenv(X509_get_default_cert_file_env());
+ if (!OPENSSL_issetugid())
+ file = (char *)getenv(X509_get_default_cert_file_env());
if (file)
ok = (X509_load_cert_crl_file(ctx,file,
X509_FILETYPE_PEM) != 0);
diff -rupN openssl-1.0.0d/crypto/x509/x509_vfy.c openssl-1.0.0d.fscaps/crypto/x509/x509_vfy.c
--- openssl-1.0.0d/crypto/x509/x509_vfy.c 2010-11-02 16:57:40.000000000 +0100
+++ openssl-1.0.0d.fscaps/crypto/x509/x509_vfy.c 2011-05-17 12:03:10.814608602 +0200
@@ -461,7 +461,7 @@ static int check_chain_extensions(X509_S
int (*cb)(int xok,X509_STORE_CTX *xctx);
int proxy_path_length = 0;
int purpose;
- int allow_proxy_certs;
+ int allow_proxy_certs = 0;
cb=ctx->verify_cb;
/* must_be_ca can have 1 of 3 values:
@@ -486,7 +486,7 @@ static int check_chain_extensions(X509_S
!!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
/* A hack to keep people who don't want to modify their
software happy */
- if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
+ if (!OPENSSL_issetugid() && getenv("OPENSSL_ALLOW_PROXY_CERTS"))
allow_proxy_certs = 1;
purpose = ctx->param->purpose;
}
diff -rupN openssl-1.0.0d/engines/ccgost/gost_ctl.c openssl-1.0.0d.fscaps/engines/ccgost/gost_ctl.c
--- openssl-1.0.0d/engines/ccgost/gost_ctl.c 2008-03-16 22:05:44.000000000 +0100
+++ openssl-1.0.0d.fscaps/engines/ccgost/gost_ctl.c 2011-05-17 10:59:37.160608658 +0200
@@ -59,13 +59,14 @@ int gost_control_func(ENGINE *e,int cmd,
const char *get_gost_engine_param(int param)
{
- char *tmp;
+ char *tmp = NULL;
if (param <0 || param >GOST_PARAM_MAX) return NULL;
if (gost_params[param]!=NULL)
{
return gost_params[param];
}
- tmp = getenv(gost_envnames[param]);
+ if (!OPENSSL_issetugid())
+ tmp = getenv(gost_envnames[param]);
if (tmp)
{
if (gost_params[param]) OPENSSL_free(gost_params[param]);
@@ -77,9 +78,10 @@ const char *get_gost_engine_param(int pa
int gost_set_default_param(int param, const char *value)
{
- const char *tmp;
+ const char *tmp = NULL;
if (param <0 || param >GOST_PARAM_MAX) return 0;
- tmp = getenv(gost_envnames[param]);
+ if (!OPENSSL_issetugid())
+ tmp = getenv(gost_envnames[param]);
/* if there is value in the environment, use it, else -passed string * */
if (!tmp) tmp=value;
if (gost_params[param]) OPENSSL_free(gost_params[param]);