apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jerenkra...@apache.org
Subject cvs commit: apr-util/test testpass.c .cvsignore Makefile.in
Date Wed, 28 May 2003 04:45:46 GMT
jerenkrantz    2003/05/27 21:45:46

  Modified:    .        CHANGES configure.in
               build    apu-hints.m4
               crypto   apr_md5.c
               test     .cvsignore Makefile.in
  Added:       test     testpass.c
  Log:
  SECURITY [httpd incident CAN-2003-0189] Address a thread safety issue with
  apr_password_validate() on AIX, Linux, Mac OS X, and possibly other platforms.
  
  We didn't move the crypt_r checks from apr to apr-util when we moved
  apr_password_validate.  Add testpass.c to ensure we don't regress.
  
  CVE: CAN-2003-0189
  Reviewed by:	Justin, Jim, Jeff
  
  Revision  Changes    Path
  1.113     +4 -0      apr-util/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apr-util/CHANGES,v
  retrieving revision 1.112
  retrieving revision 1.113
  diff -u -u -r1.112 -r1.113
  --- CHANGES	9 May 2003 10:59:20 -0000	1.112
  +++ CHANGES	28 May 2003 04:45:46 -0000	1.113
  @@ -1,5 +1,9 @@
   Changes with APR-util 0.9.4
   
  +  *) SECURITY [httpd incident CAN-2003-0189] Address a thread safety
  +     issue with apr_password_validate() on AIX, Linux, Mac OS X, and
  +     possibly other platforms.  [Jeff Trawick, Justin Erenkrantz]
  +
     *) Fix a problem with LDAP configuration which caused subsequent
        configure tests to fail since LIBS contained LDAP libraries for
        subsequent tests but LDFLAGS no longer included the path to such 
  
  
  
  1.66      +15 -0     apr-util/configure.in
  
  Index: configure.in
  ===================================================================
  RCS file: /home/cvs/apr-util/configure.in,v
  retrieving revision 1.65
  retrieving revision 1.66
  diff -u -u -r1.65 -r1.66
  --- configure.in	28 Apr 2003 12:10:41 -0000	1.65
  +++ configure.in	28 May 2003 04:45:46 -0000	1.66
  @@ -94,6 +94,21 @@
   APU_FIND_EXPAT
   APU_FIND_ICONV
   
  +AC_SEARCH_LIBS(crypt, crypt ufc)
  +AC_MSG_CHECKING(if system crypt() function is threadsafe)
  +if test "x$apu_crypt_threadsafe" = "x1"; then
  +  AC_DEFINE(APU_CRYPT_THREADSAFE, 1, [Define if the system crypt() function is threadsafe])
  +  msg="yes"
  +else
  +  msg="no"
  +fi
  +AC_MSG_RESULT([$msg])
  +
  +AC_CHECK_FUNCS(crypt_r, [ crypt_r="1" ], [ crypt_r="0" ])
  +if test "$crypt_r" = "1"; then
  +  APR_CHECK_CRYPT_R_STYLE
  +fi
  +
   so_ext=$APR_SO_EXT
   lib_target=$APR_LIB_TARGET
   AC_SUBST(so_ext)
  
  
  
  1.3       +11 -1     apr-util/build/apu-hints.m4
  
  Index: apu-hints.m4
  ===================================================================
  RCS file: /home/cvs/apr-util/build/apu-hints.m4,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -u -r1.2 -r1.3
  --- apu-hints.m4	15 Dec 2002 19:36:41 -0000	1.2
  +++ apu-hints.m4	28 May 2003 04:45:46 -0000	1.3
  @@ -18,11 +18,21 @@
       echo "Applying apr-util hints file rules for $host"
   
       case "$host" in
  -        *-ibm-aix*)
  +    *-dec-osf*)
  +        APR_SETIFNULL(apu_crypt_threadsafe, [1])
  +        ;;
  +    *-hp-hpux11.*)
  +        APR_SETIFNULL(apu_crypt_threadsafe, [1])
  +        ;;
  +    *-ibm-aix*)
           APR_SETIFNULL(apu_iconv_inbuf_const, [1])
           ;;
  +    *-ibm-os390)
  +        APR_SETIFNULL(apu_crypt_threadsafe, [1])
  +        ;;
       *-solaris2*)
           APR_SETIFNULL(apu_iconv_inbuf_const, [1])
  +        APR_SETIFNULL(apu_crypt_threadsafe, [1])
           ;;
       *-sco3.2v5*)
   	APR_SETIFNULL(apu_db_xtra_libs, [-lsocket])
  
  
  
  1.6       +43 -5     apr-util/crypto/apr_md5.c
  
  Index: apr_md5.c
  ===================================================================
  RCS file: /home/cvs/apr-util/crypto/apr_md5.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -u -r1.5 -r1.6
  --- apr_md5.c	12 Mar 2003 20:20:00 -0000	1.5
  +++ apr_md5.c	28 May 2003 04:45:46 -0000	1.6
  @@ -98,6 +98,7 @@
   #include "apr_strings.h"
   #include "apr_md5.h"
   #include "apr_lib.h"
  +#include "apu_config.h"
   
   #if APR_HAVE_STRING_H
   #include <string.h>
  @@ -108,6 +109,9 @@
   #if APR_HAVE_UNISTD_H
   #include <unistd.h>
   #endif
  +#if APR_HAVE_PTHREAD_H
  +#include <pthread.h>
  +#endif
   
   /* Constants for MD5Transform routine.
    */
  @@ -671,6 +675,32 @@
       return APR_SUCCESS;
   }
   
  +#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
  +#if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS
  +
  +#define crypt_mutex_lock()
  +#define crypt_mutex_unlock()
  +
  +#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
  +
  +static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
  +static void crypt_mutex_lock(void)
  +{
  +    pthread_mutex_lock(&crypt_mutex);
  +}
  +
  +static void crypt_mutex_unlock(void)
  +{
  +    pthread_mutex_unlock(&crypt_mutex);
  +}
  +
  +#else
  +
  +#error apr_password_validate() is not threadsafe.  rebuild APR without thread support.
  +
  +#endif
  +#endif
  +
   /*
    * Validate a plaintext password against a smashed one.  Use either
    * crypt() (if available) or apr_md5_encode(), depending upon the format
  @@ -714,14 +744,22 @@
           crypt_pw = crypt_r(passwd, hash, &buffer);
           apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
   #else
  -        /* XXX if this is a threaded build, we should hold a mutex 
  -         *     around the next two lines... but note that on some
  -         *     platforms (e.g., Solaris, HP-UX, OS/390) crypt() 
  -         *     returns a pointer to thread-specific data so we don't
  -         *     want a mutex on those platforms
  +        /* Do a bit of sanity checking since we know that crypt_r()
  +         * should always be used for threaded builds on AIX, and
  +         * problems in configure logic can result in the wrong
  +         * choice being made.
  +         */
  +#if defined(_AIX) && defined(APR_HAS_THREADS)
  +#error Configuration error!  crypt_r() should have been selected!
  +#endif
  +
  +        /* Handle thread safety issues by holding a mutex around the
  +         * call to crypt().
            */
  +        crypt_mutex_lock();
           crypt_pw = crypt(passwd, hash);
           apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
  +        crypt_mutex_unlock();
   #endif
       }
       return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
  
  
  
  1.9       +1 -0      apr-util/test/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  RCS file: /home/cvs/apr-util/test/.cvsignore,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -u -r1.8 -r1.9
  --- .cvsignore	7 Oct 2002 16:34:59 -0000	1.8
  +++ .cvsignore	28 May 2003 04:45:46 -0000	1.9
  @@ -8,6 +8,7 @@
   testdbm
   testmd4
   testmd5
  +testpass
   testqueue
   testreslist
   testrmm
  
  
  
  1.37      +6 -1      apr-util/test/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/apr-util/test/Makefile.in,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -u -r1.36 -r1.37
  --- Makefile.in	23 Apr 2003 12:25:48 -0000	1.36
  +++ Makefile.in	28 May 2003 04:45:46 -0000	1.37
  @@ -3,7 +3,7 @@
   INCLUDES = @APRUTIL_PRIV_INCLUDES@ @APR_INCLUDES@ @APRUTIL_INCLUDES@
   
   PROGRAMS = testdbm testdate testmd4 testmd5 testxml testrmm teststrmatch \
  -	testuuid testreslist testqueue testuri
  +	testuuid testreslist testqueue testuri testpass
   TARGETS = $(PROGRAMS)
   
   APRUTIL_DOTTED_VERSION=@APRUTIL_DOTTED_VERSION@
  @@ -80,4 +80,9 @@
   testuri_LDADD =  $(TARGET_LIB_PATH)
   testuri: $(testuri_OBJECTS) $(testuri_LDADD)
   	$(LINK) $(APRUTIL_LDFLAGS) $(testuri_OBJECTS) $(testuri_LDADD) $(PROGRAM_DEPENDENCIES)
  +
  +testpass_OBJECTS = testpass.lo
  +testpass_LDADD =  $(TARGET_LIB_PATH)
  +testpass: $(testpass_OBJECTS) $(testpass_LDADD)
  +	$(LINK) $(APRUTIL_LDFLAGS) $(testpass_OBJECTS) $(testpass_LDADD) $(PROGRAM_DEPENDENCIES)
   
  
  
  
  1.1                  apr-util/test/testpass.c
  
  Index: testpass.c
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  #include <assert.h>
  #include <stdio.h>
  #include <stdlib.h>
  
  #include "apr_errno.h"
  #include "apr_strings.h"
  #include "apr_file_io.h"
  #include "apr_thread_proc.h"
  #include "apr_md5.h"
  
  static struct {
      const char *password;
      const char *hash;
  } passwords[] =
  {
  /*
    passwords and hashes created with Apache's htpasswd utility like this:
    
    htpasswd -c -b passwords pass1 pass1
    htpasswd -b passwords pass2 pass2
    htpasswd -b passwords pass3 pass3
    htpasswd -b passwords pass4 pass4
    htpasswd -b passwords pass5 pass5
    htpasswd -b passwords pass6 pass6
    htpasswd -b passwords pass7 pass7
    htpasswd -b passwords pass8 pass8
    (insert Perl one-liner to convert to initializer :) )
   */
      {"pass1", "1fWDc9QWYCWrQ"},
      {"pass2", "1fiGx3u7QoXaM"},
      {"pass3", "1fzijMylTiwCs"},
      {"pass4", "nHUYc8U2UOP7s"},
      {"pass5", "nHpETGLGPwAmA"},
      {"pass6", "nHbsbWmJ3uyhc"},
      {"pass7", "nHQ3BbF0Y9vpI"},
      {"pass8", "nHZA1rViSldQk"}
  };
  static int num_passwords = sizeof(passwords) / sizeof(passwords[0]);
  
  static void check_rv(apr_status_t rv)
  {
      if (rv != APR_SUCCESS) {
          fprintf(stderr, "bailing\n");
          exit(1);
      }
  }
  
  static void test(void)
  {
      int i;
  
      for (i = 0; i < num_passwords; i++) {
          apr_status_t rv = apr_password_validate(passwords[i].password,
                                                  passwords[i].hash);
          assert(rv == APR_SUCCESS);
      }
  }
  
  #if APR_HAS_THREADS
  
  static void * APR_THREAD_FUNC testing_thread(apr_thread_t *thd,
                                               void *data)
  {
      int i;
  
      for (i = 0; i < 100; i++) {
          test();
      }
      return APR_SUCCESS;
  }
  
  static void thread_safe_test(apr_pool_t *p)
  {
  #define NUM_THR 20
      apr_thread_t *my_threads[NUM_THR];
      int i;
      apr_status_t rv;
      
      for (i = 0; i < NUM_THR; i++) {
          rv = apr_thread_create(&my_threads[i], NULL, testing_thread, NULL, p);
          check_rv(rv);
      }
  
      for (i = 0; i < NUM_THR; i++) {
          apr_thread_join(&rv, my_threads[i]);
      }
  }
  #endif
  
  int main(void)
  {
      apr_status_t rv;
      apr_pool_t *p;
  
      rv = apr_initialize();
      check_rv(rv);
      rv = apr_pool_create(&p, NULL);
      check_rv(rv);
      atexit(apr_terminate);
  
      /* before creating any threads, test it first just to check
       * for problems with the test driver
       */
      printf("dry run\n");
      test();
  
  #if APR_HAS_THREADS
      printf("thread-safe test\n");
      thread_safe_test(p);
  #endif
      
      return 0;
  }
  
  
  

Mime
View raw message