Hello community,

here is the log from the commit of package libserf for openSUSE:Factory checked 
in at 2013-08-16 11:36:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libserf (Old)
 and      /work/SRC/openSUSE:Factory/.libserf.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libserf"

Changes:
--------
--- /work/SRC/openSUSE:Factory/libserf/libserf.changes  2013-08-12 
14:27:23.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.libserf.new/libserf.changes     2013-08-16 
11:36:25.000000000 +0200
@@ -1,0 +2,19 @@
+Thu Aug 15 19:53:09 UTC 2013 - [email protected]
+
+- update to 1.3.1
+- bug fixes:
+  * endless loop if server doesn't accept Negotiate authentication.
+  * ssl/tls renegotiation fails
+  * error with ssl tunnel over proxy with KeepAlive off and
+    Basic authentication.
+  * Fixed bugs with authentication
+  * build system changes ( already covered by patches below )
+- packaging changes:
+  * remove make and libtool build requirements
+  * removed scons patches, committed upstream:
+    libserf-1.3.x-gssapi-libs.patch
+    libserf-1.3.x-libdir.patch
+    libserf-1.3.x-scons-check-exit.patch
+    libserf-1.3.x-soname.patch
+
+-------------------------------------------------------------------

Old:
----
  libserf-1.3.x-gssapi-libs.patch
  libserf-1.3.x-libdir.patch
  libserf-1.3.x-scons-check-exit.patch
  libserf-1.3.x-soname.patch
  serf-1.3.0.tar.bz2

New:
----
  serf-1.3.1.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libserf.spec ++++++
--- /var/tmp/diff_new_pack.Po7SsV/_old  2013-08-16 11:36:26.000000000 +0200
+++ /var/tmp/diff_new_pack.Po7SsV/_new  2013-08-16 11:36:26.000000000 +0200
@@ -24,7 +24,7 @@
 %define major  1
 %define minor  3
 %define SHLIBVER %minor.0.0
-Version:        1.3.0
+Version:        1.3.1
 Release:        0
 Summary:        High-Performance Asynchronous HTTP Client Library
 License:        Apache-2.0
@@ -32,21 +32,14 @@
 Source:         https://serf.googlecode.com/files/serf-%{version}.tar.bz2
 Url:            https://serf.googlecode.com
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-Patch0:         libserf-1.3.x-libdir.patch
-Patch1:         libserf-1.3.x-soname.patch
-Patch2:         libserf-1.3.x-gssapi-libs.patch
-Patch3:         libserf-1.3.x-scons-check-exit.patch
 BuildRequires:  gcc
 BuildRequires:  glibc-devel
 BuildRequires:  libapr-util1-devel >= %{minimum_apr_version}
 BuildRequires:  libapr1-devel >= %{minimum_apr_version}
 BuildRequires:  libexpat-devel
 BuildRequires:  libopenssl-devel
-BuildRequires:  libtool
-BuildRequires:  make
 BuildRequires:  openldap2-devel
 BuildRequires:  pkgconfig
-# SHLIBVERERSION introduced in 2.3 (libserf-1.3.x-soname.patch)
 BuildRequires:  scons >= 2.3
 BuildRequires:  zlib-devel
 %if %{with gssapi}
@@ -118,14 +111,8 @@
 
 %prep
 %setup -q -n "serf-%{version}"
-%patch0 -p1
-%patch1 -p1
-%patch2 -p1
-%patch3        -p1
 
 %build
-# scons expects coma separated flags
-SCONS_OPTFLAGS=`echo %{optflags} | sed "s/ /,/g"`
 scons \
        PREFIX=%{_prefix} \
        LIBDIR=%{_libdir} \
@@ -136,7 +123,7 @@
        GSSAPI=/usr/lib/mit \
 %endif
        DEBUG=yes \
-       CFLAGS="$SCONS_OPTFLAGS" \
+       CFLAGS="%{optflags}" \
        APR_STATIC=no \
        %{?_smp_mflags} 
 
@@ -146,10 +133,8 @@
 
 %check
 %if 0%{?suse_version} > 1210
-# scons expects coma separated flags
-SCONS_OPTFLAGS=`echo %{optflags} | sed "s/ /,/g"`
 scons \
-       CFLAGS=$SCONS_OPTFLAGS  \
+       CFLAGS="%{optflags}" \
        check \
        %{?_smp_mflags}
 %endif

++++++ serf-1.3.0.tar.bz2 -> serf-1.3.1.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/CHANGES new/serf-1.3.1/CHANGES
--- old/serf-1.3.0/CHANGES      2013-07-23 16:47:17.000000000 +0200
+++ new/serf-1.3.1/CHANGES      2013-08-15 21:16:24.000000000 +0200
@@ -1,4 +1,23 @@
-Serf 1.3.0 [2013-07-23, from /tags/1.3.0]
+Serf 1.3.1 [2013-08-15, from /tags/1.3.1, r????]
+  Fix issue 77: Endless loop if server doesn't accept Negotiate authentication.
+  Fix issue 114: ssl/tls renegotiation fails
+  Fix issue 120: error with ssl tunnel over proxy with KeepAlive off and
+                 Basic authentication.
+  Fixed bugs with authentication (r2057,2115,2118)
+  SCons-related fixes:
+   Fix issue 111: add flag to set custom library path
+   Fix issue 112: add soname
+   Fix issue 113: add gssapi libs in the serf pc file
+   Fix issue 115: Setting RPATH on Solaris broken in SConstruct
+   Fix issue 116: scons check should return non-zero exit staths
+   Fix issue 121: make CFLAGS, LIBS, LINKFLAGS and CPPFLAGS take a space-
+                   separated list of flags.
+   Fix issue 122: make scons PREFIX create the folder if it doesn't exist
+   Mac OS X: Fix scons --install-sandbox
+   Solaris: Fix build with cc, don't use unsupported compiler flags
+  Require SCons version 2.3.0 or higher now (for the soname support).
+
+Serf 1.3.0 [2013-07-23, from /tags/1.3.0, r2074]
   Fix issue 83: use PATH rather than URI within an ssltunnel (r1952)
   Fix issue 108: improved error reporting from the underlying socket (r1951)
   NEW: Switch to the SCons build system; retire serfmake, serf.mak, autotools
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/README new/serf-1.3.1/README
--- old/serf-1.3.0/README       2013-07-21 17:04:50.000000000 +0200
+++ new/serf-1.3.1/README       2013-08-15 11:13:20.000000000 +0200
@@ -18,14 +18,14 @@
 
 1.1. SCons build system
 
-serf uses SCons 2.x for its build system. If it is not installed on
+serf uses SCons 2.3 for its build system. If it is not installed on
 your system, then you can install it onto your system. If you do not
 have permissions, then you can download and install the "local"
 version into your home directory. When installed privately, simply
 create a symlink for 'scons' in your PATH to /path/to/scons/scons.py.
 
 Fetch the scons-local package:
-  http://prdownloads.sourceforge.net/scons/scons-local-2.0.1.tar.gz
+  http://prdownloads.sourceforge.net/scons/scons-local-2.3.0.tar.gz
 
 
 1.2 Building serf
@@ -54,6 +54,12 @@
 
 $ scons -Y /path/to/serf/source
 
+If you plan to install the library on a system that uses different
+paths for architecture dependent files, specify LIBDIR. LIBDIR defaults
+to /usr/local/lib otherwise. Example for a 64 bit GNU/Linux system:
+
+$ scons PREFIX=/usr/ LIBDIR=/usr/lib64
+
 At any point, the current settings can be examined:
 
 $ scons --help
@@ -74,6 +80,13 @@
 
 $ scons PREFIX=/some/path install
 
+Distribution package maintainers regulary install to a buildroot, and
+would normally use something like below in their build systems, with
+placeholders for the specific paths:
+
+$ scons PREFIX=/usr/ LIBDIR=/usr/lib64
+$ scons install --install-sandbox=/path/to/buildroot
+
 
 1.4 Cleaning up the build
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/SConstruct new/serf-1.3.1/SConstruct
--- old/serf-1.3.0/SConstruct   2013-07-21 17:04:50.000000000 +0200
+++ new/serf-1.3.1/SConstruct   2013-08-15 11:13:20.000000000 +0200
@@ -19,6 +19,8 @@
 import os
 import re
 
+EnsureSConsVersion(2,3,0)
+
 HEADER_FILES = ['serf.h',
                 'serf_bucket_types.h',
                 'serf_bucket_util.h',
@@ -34,23 +36,35 @@
     if val == 'none':
       val = []
     else:
-      val = val.split(',')
+      val = val.split(' ')
     return val
 
 def RawListVariable(key, help, default):
     """
     The input parameters describe a 'raw string list' option. This class
-    accepts a comma separated list and converts it to a space separated
-    list.
+    accepts a space-separated string and converts it to a list.
     """
     return (key, '%s' % (help), default, None, lambda val: _converter(val))
 
+# Custom path validator, creates directory when a specified option is set.
+# To be used to ensure a PREFIX directory is only created when installing.
+def createPathIsDirCreateWithTarget(target):
+  def my_validator(key, val, env):
+    build_targets = (map(str, BUILD_TARGETS))
+    if target in build_targets:
+      return PathVariable.PathIsDirCreate(key, val, env)
+    else:
+      return PathVariable.PathAccept(key, val, env)
+  return my_validator
+
 # default directories
 if sys.platform == 'win32':
+  default_incdir='..'
   default_libdir='..'
   default_prefix='Debug'
 else:
-  default_libdir='/usr'
+  default_incdir='/usr'
+  default_libdir='$PREFIX/lib'
   default_prefix='/usr/local'
 
 opts = Variables(files=[SAVED_CONFIG])
@@ -58,22 +72,26 @@
   PathVariable('PREFIX',
                'Directory to install under',
                default_prefix,
-               PathVariable.PathIsDir),
+               createPathIsDirCreateWithTarget('install')),
+  PathVariable('LIBDIR',
+               'Directory to install architecture dependent libraries under',
+               default_libdir,
+               createPathIsDirCreateWithTarget('install')),
   PathVariable('APR',
                "Path to apr-1-config, or to APR's install area",
-               default_libdir,
+               default_incdir,
                PathVariable.PathAccept),
   PathVariable('APU',
                "Path to apu-1-config, or to APR's install area",
-               default_libdir,
+               default_incdir,
                PathVariable.PathAccept),
   PathVariable('OPENSSL',
                "Path to OpenSSL's install area",
-               default_libdir,
+               default_incdir,
                PathVariable.PathIsDir),
   PathVariable('ZLIB',
                "Path to zlib's install area",
-               default_libdir,
+               default_incdir,
                PathVariable.PathIsDir),
   PathVariable('GSSAPI',
                "Path to GSSAPI's install area",
@@ -86,14 +104,14 @@
                "Enable using a static compiled APR",
                False),
   RawListVariable('CC', "Command name or path of the C compiler", None),
-  RawListVariable('CFLAGS', "Extra flags for the C compiler (comma separated)",
+  RawListVariable('CFLAGS', "Extra flags for the C compiler (space-separated)",
                   None),
   RawListVariable('LIBS', "Extra libraries passed to the linker, "
-                  "e.g. -l<library> (comma separated)", None),
-  RawListVariable('LINKFLAGS', "Extra flags for the linker (comma separated)",
+                  "e.g. \"-l<library1> -l<library2>\" (space separated)", 
None),
+  RawListVariable('LINKFLAGS', "Extra flags for the linker (space-separated)",
                   None),
   RawListVariable('CPPFLAGS', "Extra flags for the C preprocessor "
-                  "(comma separated)", None), 
+                  "(space separated)", None), 
   )
 
 if sys.platform == 'win32':
@@ -146,6 +164,8 @@
                   re.DOTALL)
 MAJOR, MINOR, PATCH = [int(x) for x in match.groups()]
 env.Append(MAJOR=str(MAJOR))
+env.Append(MINOR=str(MINOR))
+env.Append(PATCH=str(PATCH))
 
 # Calling external programs is okay if we're not cleaning or printing help.
 # (cleaning: no sense in fetching information; help: we may not know where
@@ -181,9 +201,11 @@
 # PLATFORM-SPECIFIC BUILD TWEAKS
 
 thisdir = os.getcwd()
-libdir = '$PREFIX/lib'
+libdir = '$LIBDIR'
 incdir = '$PREFIX/include/serf-$MAJOR'
 
+env['SHLIBVERSION']='${MINOR}.0.0'
+
 LIBNAME = 'libserf-${MAJOR}'
 if sys.platform != 'win32':
   LIBNAMESTATIC = LIBNAME
@@ -205,14 +227,12 @@
   ### gcc only. figure out appropriate test / better way to check these
   ### flags, and check for gcc.
   env.Append(CFLAGS='-std=c89')
-  env.Append(CCFLAGS=[
-               '-Wdeclaration-after-statement',
-               '-Wmissing-prototypes',
-             ])
 
-  ### -Wall is not available on Solaris
+  ### These warnings are not available on Solaris
   if sys.platform != 'sunos5': 
-    env.Append(CCFLAGS='-Wall')
+    env.Append(CCFLAGS=['-Wdeclaration-after-statement',
+                        '-Wmissing-prototypes',
+                        '-Wall'])
 
   if debug:
     env.Append(CCFLAGS='-g')
@@ -334,7 +354,10 @@
 
 # If build with gssapi, get its information and define SERF_HAVE_GSSAPI
 if gssapi and CALLOUT_OKAY:
-    env.ParseConfig('$GSSAPI --libs gssapi')
+    def parse_libs(env, cmd, unique=1):
+        env['GSSAPI_LIBS'] = cmd.strip()
+        return env.MergeFlags(cmd, unique)
+    env.ParseConfig('$GSSAPI --libs gssapi', parse_libs)
     env.Append(CPPDEFINES='SERF_HAVE_GSSAPI')
 if sys.platform == 'win32':
   env.Append(CPPDEFINES=['SERF_HAVE_SSPI'])
@@ -344,10 +367,9 @@
 # flags to set RPATH values.
 if sys.platform == 'sunos5':
   for d in env['LIBPATH']:
-    env.Append(RPATH=d)
+    env.Append(RPATH=':'+d)
 
 # Set up the construction of serf-*.pc
-# TODO: add gssapi libs
 pkgconfig = env.Textfile('serf-%d.pc' % (MAJOR,),
                          env.File('build/serf.pc.in'),
                          SUBST_DICT = {
@@ -355,7 +377,8 @@
                            '@PREFIX@': '$PREFIX',
                            '@INCLUDE_SUBDIR@': 'serf-%d' % (MAJOR,),
                            '@VERSION@': '%d.%d.%d' % (MAJOR, MINOR, PATCH),
-                           '@LIBS@': '%s %s -lz' % (apu_libs, apr_libs),
+                           '@LIBS@': '%s %s %s -lz' % (apu_libs, apr_libs,
+                                                       env.get('GSSAPI_LIBS')),
                            })
 
 env.Default(lib_static, lib_shared, pkgconfig)
@@ -371,12 +394,16 @@
 # INSTALLATION STUFF
 
 install_static = env.Install(libdir, lib_static)
-install_shared = env.Install(libdir, lib_shared)
+install_shared = env.InstallVersionedLib(libdir, lib_shared)
 
 if sys.platform == 'darwin':
+  # If --install-sandbox=<path> is specified, install_shared_path will point
+  # to a path in the sandbox. The shared library install name (id) should be 
the
+  # final targat path.
   install_shared_path = install_shared[0].abspath
+  target_install_shared_path = os.path.join(libdir, lib_shared[0].name)
   env.AddPostAction(install_shared, ('install_name_tool -id %s %s'
-                                     % (install_shared_path,
+                                     % (target_install_shared_path,
                                         install_shared_path)))
   ### construct shared lib symlinks. this also means install the lib
   ### as libserf-2.1.0.0.dylib, then add the symlinks.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/auth/auth.c new/serf-1.3.1/auth/auth.c
--- old/serf-1.3.0/auth/auth.c  2013-07-04 21:58:40.000000000 +0200
+++ new/serf-1.3.1/auth/auth.c  2013-08-15 11:00:57.000000000 +0200
@@ -23,7 +23,8 @@
 #include <apr_lib.h>
 
 static apr_status_t
-default_auth_response_handler(peer_t peer,
+default_auth_response_handler(const serf__authn_scheme_t *scheme,
+                              peer_t peer,
                               int code,
                               serf_connection_t *conn,
                               serf_request_t *request,
@@ -151,6 +152,17 @@
         if (!auth_hdr)
             continue;
 
+        if (code == 401) {
+            authn_info = serf__get_authn_info_for_server(conn);
+        } else {
+            authn_info = &ctx->proxy_authn_info;
+        }
+
+        if (authn_info->failed_authn_types & scheme->type) {
+            /* Skip this authn type since we already tried it before. */
+            continue;
+        }
+
         /* Found a matching scheme */
         status = APR_SUCCESS;
 
@@ -159,11 +171,6 @@
         serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
                       "... matched: %s\n", scheme->name);
 
-        if (code == 401) {
-            authn_info = serf__get_authn_info_for_server(conn);
-        } else {
-            authn_info = &ctx->proxy_authn_info;
-        }
         /* If this is the first time we use this scheme on this context and/or
            this connection, make sure to initialize the authentication handler 
            first. */
@@ -198,6 +205,12 @@
         */
         serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
                       "%s authentication failed.\n", scheme->name);
+
+        /* Clear per-request auth_baton when switching to next auth scheme. */
+        request->auth_baton = NULL;
+
+        /* Remember failed auth types to skip in future. */
+        authn_info->failed_authn_types |= scheme->type;
     }
 
     return status;
@@ -378,16 +391,16 @@
         authn_info = serf__get_authn_info_for_server(conn);
         if (authn_info->scheme) {
             validate_resp = authn_info->scheme->validate_response_func;
-            resp_status = validate_resp(HOST, sl.code, conn, request, response,
-                                        pool);
+            resp_status = validate_resp(authn_info->scheme, HOST, sl.code,
+                                        conn, request, response, pool);
         }
 
         /* Validate the response proxy authn headers. */
         authn_info = &ctx->proxy_authn_info;
         if (!resp_status && authn_info->scheme) {
             validate_resp = authn_info->scheme->validate_response_func;
-            resp_status = validate_resp(PROXY, sl.code, conn, request, 
response,
-                                        pool);
+            resp_status = validate_resp(authn_info->scheme, PROXY, sl.code,
+                                        conn, request, response, pool);
         }
 
         if (resp_status) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/auth/auth.h new/serf-1.3.1/auth/auth.h
--- old/serf-1.3.0/auth/auth.h  2013-06-26 18:21:31.000000000 +0200
+++ new/serf-1.3.1/auth/auth.h  2013-08-15 11:00:57.000000000 +0200
@@ -78,7 +78,8 @@
                                              const char *method,
                                              const char *uri,
                                              serf_bucket_t *hdrs_bkt);
-apr_status_t serf__validate_response_digest_auth(peer_t peer,
+apr_status_t serf__validate_response_digest_auth(const serf__authn_scheme_t 
*scheme,
+                                                 peer_t peer,
                                                  int code,
                                                  serf_connection_t *conn,
                                                  serf_request_t *request,
@@ -108,7 +109,8 @@
                                              const char *method,
                                              const char *uri,
                                              serf_bucket_t *hdrs_bkt);
-apr_status_t serf__validate_response_spnego_auth(peer_t peer,
+apr_status_t serf__validate_response_spnego_auth(const serf__authn_scheme_t 
*scheme,
+                                                 peer_t peer,
                                                  int code,
                                                  serf_connection_t *conn,
                                                  serf_request_t *request,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/auth/auth_digest.c 
new/serf-1.3.1/auth/auth_digest.c
--- old/serf-1.3.0/auth/auth_digest.c   2013-07-21 16:27:03.000000000 +0200
+++ new/serf-1.3.1/auth/auth_digest.c   2013-08-15 11:00:57.000000000 +0200
@@ -438,7 +438,8 @@
 }
 
 apr_status_t
-serf__validate_response_digest_auth(peer_t peer,
+serf__validate_response_digest_auth(const serf__authn_scheme_t *scheme,
+                                    peer_t peer,
                                     int code,
                                     serf_connection_t *conn,
                                     serf_request_t *request,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/auth/auth_spnego.c 
new/serf-1.3.1/auth/auth_spnego.c
--- old/serf-1.3.0/auth/auth_spnego.c   2013-07-04 21:58:40.000000000 +0200
+++ new/serf-1.3.1/auth/auth_spnego.c   2013-08-15 11:00:57.000000000 +0200
@@ -212,7 +212,11 @@
 
     switch(status) {
     case APR_SUCCESS:
-        gss_info->state = gss_api_auth_completed;
+        if (output_buf.length == 0) {
+            gss_info->state = gss_api_auth_completed;
+        } else {
+            gss_info->state = gss_api_auth_in_progress;
+        }
         break;
     case APR_EAGAIN:
         gss_info->state = gss_api_auth_in_progress;
@@ -242,6 +246,7 @@
         int code,
         gss_authn_info_t *gss_info,
         serf_connection_t *conn,
+        serf_request_t *request,
         const char *auth_hdr,
         apr_pool_t *pool)
 {
@@ -306,6 +311,14 @@
             break;
     }
 
+    if (request->auth_baton && !token) {
+        /* We provided token with this request, but server responded with empty
+           authentication header. This means server rejected our credentials.
+           XXX: Probably we need separate error code for this case like
+           SERF_ERROR_AUTHN_CREDS_REJECTED? */
+        return SERF_ERROR_AUTHN_FAILED;
+    }
+
     /* If the server didn't provide us with a token, start with a new initial
        step in the SPNEGO authentication. */
     if (!token) {
@@ -404,6 +417,7 @@
                    code,
                    gss_info,
                    request->conn,
+                   request,
                    auth_hdr,
                    pool);
 }
@@ -431,6 +445,10 @@
         serf_bucket_headers_setn(hdrs_bkt, gss_info->header,
                                  gss_info->value);
 
+        /* Remember that we're using this request for authentication
+           handshake. */
+        request->auth_baton = (void*) TRUE;
+
         /* We should send each token only once. */
         gss_info->header = NULL;
         gss_info->value = NULL;
@@ -469,6 +487,7 @@
                                  code,
                                  gss_info,
                                  conn,
+                                 request,
                                  0l,    /* no response authn header */
                                  conn->pool);
                 if (status)
@@ -476,6 +495,11 @@
 
                 serf_bucket_headers_setn(hdrs_bkt, gss_info->header,
                                          gss_info->value);
+
+                /* Remember that we're using this request for authentication
+                   handshake. */
+                request->auth_baton = (void*) TRUE;
+
                 /* We should send each token only once. */
                 gss_info->header = NULL;
                 gss_info->value = NULL;
@@ -486,13 +510,63 @@
     return APR_SUCCESS;
 }
 
+/**
+ * Baton passed to the get_auth_header callback function.
+ */
+typedef struct {
+    const char *hdr_name;
+    const char *auth_name;
+    const char *hdr_value;
+    apr_pool_t *pool;
+} get_auth_header_baton_t;
+
+static int
+get_auth_header_cb(void *baton,
+                   const char *key,
+                   const char *header)
+{
+    get_auth_header_baton_t *b = baton;
+
+    /* We're only interested in xxxx-Authenticate headers. */
+    if (strcasecmp(key, b->hdr_name) != 0)
+        return 0;
+
+    /* Check if header value starts with interesting auth name. */
+    if (strncmp(header, b->auth_name, strlen(b->auth_name)) == 0) {
+        /* Save interesting header value and stop iteration. */
+        b->hdr_value = apr_pstrdup(b->pool,  header);
+        return 1;
+    }
+
+    return 0;
+}
+
+static const char *
+get_auth_header(serf_bucket_t *hdrs,
+                const char *hdr_name,
+                const char *auth_name,
+                apr_pool_t *pool)
+{
+    get_auth_header_baton_t b;
+
+    b.auth_name = hdr_name;
+    b.hdr_name = auth_name;
+    b.hdr_value = NULL;
+    b.pool = pool;
+
+    serf_bucket_headers_do(hdrs, get_auth_header_cb, &b);
+
+    return b.hdr_value;
+}
+
 /* Function is called when 2xx responses are received. Normally we don't
  * have to do anything, except for the first response after the
  * authentication handshake. This specific response includes authentication
  * data which should be validated by the client (mutual authentication).
  */
 apr_status_t
-serf__validate_response_spnego_auth(peer_t peer,
+serf__validate_response_spnego_auth(const serf__authn_scheme_t *scheme,
+                                    peer_t peer,
                                     int code,
                                     serf_connection_t *conn,
                                     serf_request_t *request,
@@ -524,11 +598,23 @@
         apr_status_t status;
 
         hdrs = serf_bucket_response_get_headers(response);
-        auth_hdr_val = serf_bucket_headers_get(hdrs, auth_hdr_name);
+        auth_hdr_val = get_auth_header(hdrs, auth_hdr_name, scheme->name,
+                                       pool);
+
+        if (auth_hdr_val) {
+            status = do_auth(peer, code, gss_info, conn, request, auth_hdr_val,
+                             pool);
+            if (status) {
+                return status;
+            }
+        } else {
+            /* No Authenticate headers, nothing to validate: authentication
+               completed.*/
+            gss_info->state = gss_api_auth_completed;
 
-        status = do_auth(peer, code, gss_info, conn, auth_hdr_val, pool);
-        if (status)
-            return status;
+            serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
+                          "SPNEGO handshake completed.\n");
+        }
     }
 
     if (gss_info->state == gss_api_auth_completed) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/build/check.py 
new/serf-1.3.1/build/check.py
--- old/serf-1.3.0/build/check.py       2013-07-21 16:24:52.000000000 +0200
+++ new/serf-1.3.1/build/check.py       2013-08-05 10:05:20.000000000 +0200
@@ -48,9 +48,11 @@
       subprocess.check_call([SERF_RESPONSE_EXE, case])
     except subprocess.CalledProcessError:
       print "ERROR: test case %s failed" % (case)
+      sys.exit(1)
 
   print "== Running the unit tests =="
   try:
     subprocess.check_call(TEST_ALL_EXE)
   except subprocess.CalledProcessError:
     print "ERROR: test(s) failed in test_all"
+    sys.exit(1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/outgoing.c new/serf-1.3.1/outgoing.c
--- old/serf-1.3.0/outgoing.c   2013-07-21 16:27:03.000000000 +0200
+++ new/serf-1.3.1/outgoing.c   2013-08-15 11:00:57.000000000 +0200
@@ -81,6 +81,46 @@
     return APR_SUCCESS;
 }
 
+/* Check if there is data waiting to be sent over the socket. This can happen
+   in two situations:
+   - The connection queue has atleast one request with unwritten data.
+   - All requests are written and the ssl layer wrote some data while reading
+     the response. This can happen when the server triggers a renegotiation,
+     e.g. after the first and only request on that connection was received.
+   Returns 1 if data is pending on CONN, NULL if not.
+   If NEXT_REQ is not NULL, it will be filled in with the next available 
request
+   with unwritten data. */
+static int
+request_or_data_pending(serf_request_t **next_req, serf_connection_t *conn)
+{
+    serf_request_t *request = conn->requests;
+
+    while (request != NULL && request->req_bkt == NULL &&
+           request->writing_started)
+        request = request->next;
+
+    if (next_req)
+        *next_req = request;
+
+    if (request != NULL) {
+        return 1;
+    } else if (conn->ostream_head) {
+        const char *dummy;
+        apr_size_t len;
+        apr_status_t status;
+
+        status = serf_bucket_peek(conn->ostream_head, &dummy,
+                                  &len);
+        if (!SERF_BUCKET_READ_ERROR(status) && len) {
+            serf__log_skt(CONN_VERBOSE, __FILE__, conn->skt,
+                          "All requests written but still data pending.\n");
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
 /* Update the pollset for this connection. We tweak the pollset based on
  * whether we want to read and/or write, given conditions within the
  * connection. If the connection is not (yet) in the pollset, then it
@@ -126,7 +166,6 @@
                 conn->state != SERF_CONN_CLOSING)
                 desc.reqevents |= APR_POLLOUT;
             else {
-                serf_request_t *request = conn->requests;
 
                 if ((conn->probable_keepalive_limit &&
                      conn->completed_requests > 
conn->probable_keepalive_limit) ||
@@ -134,13 +173,9 @@
                      conn->completed_requests - conn->completed_responses >=
                      conn->max_outstanding_requests)) {
                         /* we wouldn't try to write any way right now. */
-                    }
-                else {
-                    while (request != NULL && request->req_bkt == NULL &&
-                           request->written)
-                        request = request->next;
-                    if (request != NULL)
-                        desc.reqevents |= APR_POLLOUT;
+                }
+                else if (request_or_data_pending(NULL, conn)) {
+                    desc.reqevents |= APR_POLLOUT;
                 }
             }
         }
@@ -544,8 +579,12 @@
     while (old_reqs) {
         /* If we haven't started to write the connection, bring it over
          * unchanged to our new socket.
+         * Do not copy a CONNECT request to the new connection, the ssl tunnel
+         * setup code will create a new CONNECT request already.
          */
-        if (requeue_requests && !old_reqs->written) {
+        if (requeue_requests && !old_reqs->writing_started &&
+            !old_reqs->ssltunnel) {
+
             serf_request_t *req = old_reqs;
             old_reqs = old_reqs->next;
             req->next = NULL;
@@ -672,8 +711,6 @@
 /* write data out to the connection */
 static apr_status_t write_to_connection(serf_connection_t *conn)
 {
-    serf_request_t *request = conn->requests;
-
     if (conn->probable_keepalive_limit &&
         conn->completed_requests > conn->probable_keepalive_limit) {
 
@@ -684,21 +721,16 @@
         return APR_SUCCESS;
     }
 
-    /* Find a request that has data which needs to be delivered. */
-    while (request != NULL &&
-           request->req_bkt == NULL && request->written)
-        request = request->next;
-
-    /* assert: request != NULL || conn->vec_len */
-
     /* Keep reading and sending until we run out of stuff to read, or
      * writing would block.
      */
     while (1) {
+        serf_request_t *request;
         int stop_reading = 0;
         apr_status_t status;
         apr_status_t read_status;
-        serf_bucket_t *ostreamt, *ostreamh;
+        serf_bucket_t *ostreamt;
+        serf_bucket_t *ostreamh;
         int max_outstanding_requests = conn->max_outstanding_requests;
 
         /* If we're setting up an ssl tunnel, we can't send real requests
@@ -738,14 +770,11 @@
         /* We may need to move forward to a request which has something
          * to write.
          */
-        while (request != NULL &&
-               request->req_bkt == NULL && request->written)
-            request = request->next;
-
-        if (request == NULL) {
+        if (!request_or_data_pending(&request, conn)) {
             /* No more requests (with data) are registered with the
-             * connection. Let's update the pollset so that we don't
-             * try to write to this socket again.
+             * connection, and no data is pending on the outgoing stream.
+             * Let's update the pollset so that we don't try to write to this
+             * socket again.
              */
             conn->dirty_conn = 1;
             conn->ctx->dirty_pollset = 1;
@@ -757,17 +786,19 @@
             return status;
         }
 
-        if (request->req_bkt == NULL) {
-            read_status = setup_request(request);
-            if (read_status) {
-                /* Something bad happened. Propagate any errors. */
-                return read_status;
+        if (request) {
+            if (request->req_bkt == NULL) {
+                read_status = setup_request(request);
+                if (read_status) {
+                    /* Something bad happened. Propagate any errors. */
+                    return read_status;
+                }
             }
-        }
 
-        if (!request->written) {
-            request->written = 1;
-            serf_bucket_aggregate_append(ostreamt, request->req_bkt);
+            if (!request->writing_started) {
+                request->writing_started = 1;
+                serf_bucket_aggregate_append(ostreamt, request->req_bkt);
+            }
         }
 
         /* ### optimize at some point by using read_for_sendfile */
@@ -833,7 +864,8 @@
             conn->dirty_conn = 1;
             conn->ctx->dirty_pollset = 1;
         }
-        else if (read_status && conn->hit_eof && conn->vec_len == 0) {
+        else if (request && read_status && conn->hit_eof &&
+                 conn->vec_len == 0) {
             /* If we hit the end of the request bucket and all of its data has
              * been written, then clear it out to signify that we're done
              * sending the request. On the next iteration through this loop:
@@ -897,8 +929,7 @@
 
          If the authentication was tried, but failed, pass the response
          to the application, maybe it can do better. */
-      if (APR_STATUS_IS_EOF(status) ||
-          APR_STATUS_IS_EAGAIN(status)) {
+      if (status) {
           return status;
       }
     }
@@ -1060,7 +1091,7 @@
          * sending the SSL 'close notify' shutdown alert), we'll reset the
          * connection and open a new one.
          */
-        if (request->req_bkt || !request->written) {
+        if (request->req_bkt || !request->writing_started) {
             const char *data;
             apr_size_t len;
 
@@ -1118,6 +1149,14 @@
          * treat that as a success.
          */
         if (APR_STATUS_IS_EAGAIN(status)) {
+            /* It is possible that while reading the response, the ssl layer
+               has prepared some data to send. If this was the last request,
+               serf will not check for socket writability, so force this here.
+             */
+            if (request_or_data_pending(&request, conn) && !request) {
+                conn->dirty_conn = 1;
+                conn->ctx->dirty_pollset = 1;
+            }
             status = APR_SUCCESS;
             goto error;
         }
@@ -1182,7 +1221,7 @@
          * update the pollset. We don't want to read from this socket any
          * more. We are definitely done with this loop, too.
          */
-        if (request == NULL || !request->written) {
+        if (request == NULL || !request->writing_started) {
             conn->dirty_conn = 1;
             conn->ctx->dirty_pollset = 1;
             status = APR_SUCCESS;
@@ -1469,9 +1508,10 @@
     request->req_bkt = NULL;
     request->resp_bkt = NULL;
     request->priority = priority;
-    request->written = 0;
+    request->writing_started = 0;
     request->ssltunnel = ssltunnel;
     request->next = NULL;
+    request->auth_baton = NULL;
 
     return request;
 }
@@ -1515,7 +1555,7 @@
     prev = NULL;
 
     /* Find a request that has data which needs to be delivered. */
-    while (iter != NULL && iter->req_bkt == NULL && iter->written) {
+    while (iter != NULL && iter->req_bkt == NULL && iter->writing_started) {
         prev = iter;
         iter = iter->next;
     }
@@ -1574,7 +1614,7 @@
 
 apr_status_t serf_request_is_written(serf_request_t *request)
 {
-    if (request->written && !request->req_bkt)
+    if (request->writing_started && !request->req_bkt)
         return APR_SUCCESS;
 
     return APR_EBUSY;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/serf.h new/serf-1.3.1/serf.h
--- old/serf-1.3.0/serf.h       2013-07-02 07:36:41.000000000 +0200
+++ new/serf-1.3.1/serf.h       2013-08-05 11:59:59.000000000 +0200
@@ -1062,7 +1062,7 @@
 /* Version info */
 #define SERF_MAJOR_VERSION 1
 #define SERF_MINOR_VERSION 3
-#define SERF_PATCH_VERSION 0
+#define SERF_PATCH_VERSION 1
 
 /* Version number string */
 #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/serf_private.h 
new/serf-1.3.1/serf_private.h
--- old/serf-1.3.0/serf_private.h       2013-07-21 16:21:27.000000000 +0200
+++ new/serf-1.3.1/serf_private.h       2013-08-15 11:00:57.000000000 +0200
@@ -93,7 +93,7 @@
 
     serf_bucket_t *resp_bkt;
 
-    int written;
+    int writing_started;
     int priority;
     /* 1 if this is a request to setup a SSL tunnel, 0 for normal requests. */
     int ssltunnel;
@@ -117,6 +117,8 @@
     const serf__authn_scheme_t *scheme;
 
     void *baton;
+
+    int failed_authn_types;
 } serf__authn_info_t;
 
 struct serf_context_t {
@@ -352,7 +354,8 @@
  * (if needed).
  */
 typedef apr_status_t
-(*serf__validate_response_func_t)(peer_t peer,
+(*serf__validate_response_func_t)(const serf__authn_scheme_t *scheme,
+                                  peer_t peer,
                                   int code,
                                   serf_connection_t *conn,
                                   serf_request_t *request,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.0/test/test_context.c 
new/serf-1.3.1/test/test_context.c
--- old/serf-1.3.0/test/test_context.c  2013-07-21 16:21:27.000000000 +0200
+++ new/serf-1.3.1/test/test_context.c  2013-08-15 11:00:57.000000000 +0200
@@ -1930,13 +1930,16 @@
 /* Test if serf can successfully authenticate to a proxy used for an ssl
    tunnel. Retry the authentication a few times to test requeueing of the 
    CONNECT request. */
-static void ssltunnel_basic_auth(CuTest *tc, const char *resp_hdrs)
+static void ssltunnel_basic_auth(CuTest *tc, const char *server_resp_hdrs,
+                                 const char *proxy_resp_hdrs)
 {
     test_baton_t *tb;
     handler_baton_t handler_ctx[1];
     int num_requests_sent, num_requests_recvd;
     test_server_message_t message_list_server[2];
+    test_server_action_t action_list_proxy[7];
     test_server_action_t action_list_server[2];
+    apr_pool_t *test_pool = tc->testBaton;
     apr_status_t status;
 
     test_server_message_t message_list_proxy[] = {
@@ -1960,35 +1963,47 @@
             "Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF
             CRLF },
     };
-    test_server_action_t action_list_proxy[] = {
-        {SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF
-            "Transfer-Encoding: chunked" CRLF
-            "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
-            CRLF
-            "1" CRLF CRLF
-            "0" CRLF CRLF},
-        {SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF
-            "Transfer-Encoding: chunked" CRLF
-            "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
-            CRLF
-            "1" CRLF CRLF
-            "0" CRLF CRLF},
-        {SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF
-            "Transfer-Encoding: chunked" CRLF
-            "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
-            CRLF
-            "1" CRLF CRLF
-            "0" CRLF CRLF},
-        {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
-        /* Forward the remainder of the data to the server without validation 
*/
-        {PROXY_FORWARD, "https://localhost:"; SERV_PORT_STR},
-        /* If the client or the server closes the connection, stop 
forwarding.*/
-        {SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
-        /* Again after disconnect. */
-        {PROXY_FORWARD, "https://localhost:"; SERV_PORT_STR},
-    };
 
-    apr_pool_t *test_pool = tc->testBaton;
+    action_list_proxy[0].kind = SERVER_RESPOND;
+    action_list_proxy[0].text = apr_psprintf(test_pool,
+        "HTTP/1.1 407 Unauthorized" CRLF
+        "Transfer-Encoding: chunked" CRLF
+        "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
+        "%s"
+        CRLF
+        "1" CRLF CRLF
+        "0" CRLF CRLF, proxy_resp_hdrs);
+    action_list_proxy[1].kind = SERVER_RESPOND;
+    action_list_proxy[1].text = apr_psprintf(test_pool,
+        "HTTP/1.1 407 Unauthorized" CRLF
+        "Transfer-Encoding: chunked" CRLF
+        "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
+        "%s"
+        CRLF
+        "1" CRLF CRLF
+        "0" CRLF CRLF, proxy_resp_hdrs);
+
+    action_list_proxy[2].kind = SERVER_RESPOND;
+    action_list_proxy[2].text = apr_psprintf(test_pool,
+        "HTTP/1.1 407 Unauthorized" CRLF
+        "Transfer-Encoding: chunked" CRLF
+        "Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
+        "%s"
+        CRLF
+        "1" CRLF CRLF
+        "0" CRLF CRLF, proxy_resp_hdrs);
+
+    action_list_proxy[3].kind = SERVER_RESPOND;
+    action_list_proxy[3].text = CHUNKED_EMPTY_RESPONSE;
+    /* Forward the remainder of the data to the server without validation */
+    action_list_proxy[4].kind = PROXY_FORWARD;
+    action_list_proxy[4].text = "https://localhost:"; SERV_PORT_STR;
+    /* If the client or the server closes the connection, stop forwarding.*/
+    action_list_proxy[5].kind = SERVER_RESPOND;
+    action_list_proxy[5].text = CHUNKED_EMPTY_RESPONSE;
+    /* Again after disconnect. */
+    action_list_proxy[6].kind = PROXY_FORWARD;
+    action_list_proxy[6].text = "https://localhost:"; SERV_PORT_STR;
 
     /* Make the server also require Basic authentication */
     message_list_server[0].text =
@@ -2019,7 +2034,7 @@
         "%s"
         CRLF
         "1" CRLF CRLF
-        "0" CRLF CRLF, resp_hdrs);
+        "0" CRLF CRLF, server_resp_hdrs);
     action_list_server[1].kind = SERVER_RESPOND;
     action_list_server[1].text = CHUNKED_EMPTY_RESPONSE;
 
@@ -2064,12 +2079,20 @@
 
 static void test_ssltunnel_basic_auth(CuTest *tc)
 {
-    ssltunnel_basic_auth(tc, "");
+    /* KeepAlive On for both proxy and server */
+    ssltunnel_basic_auth(tc, "", "");
+}
+
+static void test_ssltunnel_basic_auth_server_has_keepalive_off(CuTest *tc)
+{
+    /* Add Connection:Close header to server response */
+    ssltunnel_basic_auth(tc, "Connection: close" CRLF, "");
 }
 
-static void test_ssltunnel_basic_auth_keepalive_off(CuTest *tc)
+static void test_ssltunnel_basic_auth_proxy_has_keepalive_off(CuTest *tc)
 {
-    ssltunnel_basic_auth(tc, "Connection: close" CRLF);
+    /* Add Connection:Close header to proxy response */
+    ssltunnel_basic_auth(tc, "", "Connection: close" CRLF);
 }
 
 static apr_status_t
@@ -2217,7 +2240,8 @@
     SUITE_ADD_TEST(suite, test_setup_ssltunnel);
     SUITE_ADD_TEST(suite, test_ssltunnel_no_creds_cb);
     SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth);
-    SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_keepalive_off);
+    SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_server_has_keepalive_off);
+    SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_proxy_has_keepalive_off);
     SUITE_ADD_TEST(suite, test_ssltunnel_digest_auth);
 
     return suite;

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to