diff --git a/configure.ac b/configure.ac index 458882a..c971ab6 100644 --- a/configure.ac +++ b/configure.ac @@ -38,7 +38,7 @@ AC_DEFINE(ICE_t, 1, [Xtrans transport type]) # Checks for library functions. AC_CHECK_LIB([bsd], [arc4random_buf]) -AC_CHECK_FUNCS([asprintf arc4random_buf]) +AC_CHECK_FUNCS([asprintf arc4random_buf getentropy]) # Allow checking code with lint, sparse, etc. XORG_WITH_LINT diff --git a/configure.ac.cve-2017-2626 b/configure.ac.cve-2017-2626 new file mode 100644 index 0000000..458882a --- /dev/null +++ b/configure.ac.cve-2017-2626 @@ -0,0 +1,53 @@ + +# Initialize Autoconf +AC_PREREQ([2.60]) +AC_INIT([libICE], [1.0.9], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libICE]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) + +# Set common system defines for POSIX extensions, such as _GNU_SOURCE +# Must be called before any macros that run the compiler (like +# AC_PROG_LIBTOOL or XORG_DEFAULT_OPTIONS) to avoid autoconf errors. +AC_USE_SYSTEM_EXTENSIONS + +# Initialize Automake +AM_INIT_AUTOMAKE([foreign dist-bzip2]) + +# Initialize libtool +AC_PROG_LIBTOOL + +# Require xorg-macros minimum of 1.12 for DocBook external references +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.12 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.12) +XORG_DEFAULT_OPTIONS +XORG_ENABLE_DOCS +XORG_ENABLE_SPECS +XORG_WITH_XMLTO(0.0.22) +XORG_WITH_FOP +XORG_WITH_XSLTPROC +XORG_CHECK_SGML_DOCTOOLS(1.8) + +# Obtain compiler/linker options for depedencies +PKG_CHECK_MODULES(ICE, xproto xtrans) + +# Transport selection macro from xtrans.m4 +XTRANS_CONNECTION_FLAGS +AC_DEFINE(ICE_t, 1, [Xtrans transport type]) + +# Checks for library functions. +AC_CHECK_LIB([bsd], [arc4random_buf]) +AC_CHECK_FUNCS([asprintf arc4random_buf]) + +# Allow checking code with lint, sparse, etc. +XORG_WITH_LINT +XORG_LINT_LIBRARY([ICE]) +LINT_FLAGS="${LINT_FLAGS} ${ICE_CFLAGS} ${XTRANS_CFLAGS}" + +AC_CONFIG_FILES([Makefile + doc/Makefile + specs/Makefile + src/Makefile + ice.pc]) +AC_OUTPUT diff --git a/src/iceauth.c b/src/iceauth.c index ef66626..9b77eac 100644 --- a/src/iceauth.c +++ b/src/iceauth.c @@ -42,31 +42,19 @@ Author: Ralph Mor, X Consortium static int was_called_state; -/* - * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by - * the SI. It is not part of standard ICElib. - */ +#ifndef HAVE_ARC4RANDOM_BUF - -char * -IceGenerateMagicCookie ( +static void +emulate_getrandom_buf ( + char *auth, int len ) { - char *auth; -#ifndef HAVE_ARC4RANDOM_BUF long ldata[2]; int seed; int value; int i; -#endif - if ((auth = malloc (len + 1)) == NULL) - return (NULL); - -#ifdef HAVE_ARC4RANDOM_BUF - arc4random_buf(auth, len); -#else #ifdef ITIMER_REAL { struct timeval now; @@ -74,13 +62,13 @@ IceGenerateMagicCookie ( ldata[0] = now.tv_sec; ldata[1] = now.tv_usec; } -#else +#else /* ITIMER_REAL */ { long time (); ldata[0] = time ((long *) 0); ldata[1] = getpid (); } -#endif +#endif /* ITIMER_REAL */ seed = (ldata[0]) + (ldata[1] << 16); srand (seed); for (i = 0; i < len; i++) @@ -88,7 +76,46 @@ IceGenerateMagicCookie ( value = rand (); auth[i] = value & 0xff; } -#endif +} + +static void +arc4random_buf ( + char *auth, + int len +) +{ + int ret; + +#if HAVE_GETENTROPY + /* weak emulation of arc4random through the entropy libc */ + ret = getentropy (auth, len); + if (ret == 0) + return; +#endif /* HAVE_GETENTROPY */ + + emulate_getrandom_buf (auth, len); +} + +#endif /* !defined(HAVE_ARC4RANDOM_BUF) */ + +/* + * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by + * the SI. It is not part of standard ICElib. + */ + + +char * +IceGenerateMagicCookie ( + int len +) +{ + char *auth; + + if ((auth = malloc (len + 1)) == NULL) + return (NULL); + + arc4random_buf (auth, len); + auth[len] = '\0'; return (auth); } diff --git a/src/iceauth.c.cve-2017-2626 b/src/iceauth.c.cve-2017-2626 new file mode 100644 index 0000000..ef66626 --- /dev/null +++ b/src/iceauth.c.cve-2017-2626 @@ -0,0 +1,254 @@ +/****************************************************************************** + + +Copyright 1993, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +Author: Ralph Mor, X Consortium +******************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include + +#include +#define Time_t time_t + +#ifdef HAVE_LIBBSD +#include /* for arc4random_buf() */ +#endif + +static int was_called_state; + +/* + * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by + * the SI. It is not part of standard ICElib. + */ + + +char * +IceGenerateMagicCookie ( + int len +) +{ + char *auth; +#ifndef HAVE_ARC4RANDOM_BUF + long ldata[2]; + int seed; + int value; + int i; +#endif + + if ((auth = malloc (len + 1)) == NULL) + return (NULL); + +#ifdef HAVE_ARC4RANDOM_BUF + arc4random_buf(auth, len); +#else +#ifdef ITIMER_REAL + { + struct timeval now; + X_GETTIMEOFDAY (&now); + ldata[0] = now.tv_sec; + ldata[1] = now.tv_usec; + } +#else + { + long time (); + ldata[0] = time ((long *) 0); + ldata[1] = getpid (); + } +#endif + seed = (ldata[0]) + (ldata[1] << 16); + srand (seed); + for (i = 0; i < len; i++) + { + value = rand (); + auth[i] = value & 0xff; + } +#endif + auth[len] = '\0'; + return (auth); +} + + + +IcePoAuthStatus +_IcePoMagicCookie1Proc ( + IceConn iceConn, + IcePointer *authStatePtr, + Bool cleanUp, + Bool swap, + int authDataLen, + IcePointer authData, + int *replyDataLenRet, + IcePointer *replyDataRet, + char **errorStringRet +) +{ + if (cleanUp) + { + /* + * We didn't allocate any state. We're done. + */ + + return (IcePoAuthDoneCleanup); + } + + *errorStringRet = NULL; + + if (*authStatePtr == NULL) + { + /* + * This is the first time we're being called. Search the + * authentication data for the first occurence of + * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string. + */ + + unsigned short length; + char *data; + + _IceGetPoAuthData ("ICE", iceConn->connection_string, + "MIT-MAGIC-COOKIE-1", &length, &data); + + if (!data) + { + const char *tempstr = + "Could not find correct MIT-MAGIC-COOKIE-1 authentication"; + + *errorStringRet = strdup(tempstr); + + return (IcePoAuthFailed); + } + else + { + *authStatePtr = (IcePointer) &was_called_state; + + *replyDataLenRet = length; + *replyDataRet = data; + + return (IcePoAuthHaveReply); + } + } + else + { + /* + * We should never get here for MIT-MAGIC-COOKIE-1 since it is + * a single pass authentication method. + */ + + const char *tempstr = + "MIT-MAGIC-COOKIE-1 authentication internal error"; + + *errorStringRet = strdup(tempstr); + + return (IcePoAuthFailed); + } +} + +IcePoAuthProc _IcePoAuthProcs[] = {_IcePoMagicCookie1Proc}; + + +IcePaAuthStatus +_IcePaMagicCookie1Proc ( + IceConn iceConn, + IcePointer *authStatePtr, + Bool swap, + int authDataLen, + IcePointer authData, + int *replyDataLenRet, + IcePointer *replyDataRet, + char **errorStringRet +) +{ + *errorStringRet = NULL; + *replyDataLenRet = 0; + *replyDataRet = NULL; + + if (*authStatePtr == NULL) + { + /* + * This is the first time we're being called. We don't have + * any data to pass to the other client. + */ + + *authStatePtr = (IcePointer) &was_called_state; + + return (IcePaAuthContinue); + } + else + { + /* + * Search the authentication data for the first occurence of + * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string. + */ + + unsigned short length; + char *data; + + _IceGetPaAuthData ("ICE", iceConn->connection_string, + "MIT-MAGIC-COOKIE-1", &length, &data); + + if (data) + { + IcePaAuthStatus stat; + + if (authDataLen == length && + memcmp (authData, data, authDataLen) == 0) + { + stat = IcePaAuthAccepted; + } + else + { + const char *tempstr + = "MIT-MAGIC-COOKIE-1 authentication rejected"; + + *errorStringRet = strdup(tempstr); + + stat = IcePaAuthRejected; + } + + free (data); + return (stat); + } + else + { + /* + * We should never get here because in the ConnectionReply + * we should have passed all the valid methods. So we should + * always find a valid entry. + */ + + const char *tempstr = + "MIT-MAGIC-COOKIE-1 authentication internal error"; + + *errorStringRet = strdup(tempstr); + + return (IcePaAuthFailed); + } + } +} + +IcePaAuthProc _IcePaAuthProcs[] = {_IcePaMagicCookie1Proc};