Commit 82ca5271 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

- Alexey Borzov filed bug report #2535504

  (http://curl.haxx.se/bug/view.cgi?id=2535504) pointing out that realms with
  quoted quotation marks in HTTP Digest headers didn't work. I've now added
  test case 1095 that verifies my fix.
parent f29e3835
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -7,6 +7,11 @@
                                  Changelog

Daniel Stenberg (26 Jan 2009)
- Alexey Borzov filed bug report #2535504
  (http://curl.haxx.se/bug/view.cgi?id=2535504) pointing out that realms with
  quoted quotation marks in HTTP Digest headers didn't work. I've now added 
  test case 1095 that verifies my fix.

- Craig A West brought CURLOPT_NOPROXY and the corresponding --noproxy option.
  They basically offer the same thing the NO_PROXY environment variable only
  offered previously: list a set of host names that shall not use the proxy
+2 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ This release includes the following bugfixes:

 o missing ssh.obj in VS makefiles
 o FTP ;type=i URLs now work with CURLOPT_PROXY_TRANSFER_MODE in Turkish locale
 o realms with quoted quotation marks in HTTP Digest headers

This release includes the following known bugs:

@@ -23,6 +24,6 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and
advice from friends like these:

 Lisa Xu, Daniel Fandrich, Craig A West
 Lisa Xu, Daniel Fandrich, Craig A West, Alexey Borzov

        Thanks! (and sorry if I forgot to mention someone)
+78 −18
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -47,6 +47,77 @@
/* The last #include file should be: */
#include "memdebug.h"

#define MAX_VALUE_LENGTH 256
#define MAX_CONTENT_LENGTH 1024

/*
 * Return 0 on success and then the buffers are filled in fine.
 *
 * Non-zero means failure to parse.
 */
static int get_pair(const char *str, char *value, char *content,
                    const char **endptr)
{
  int c;
  bool starts_with_quote = FALSE;
  bool escape = FALSE;

  for(c=MAX_VALUE_LENGTH-1; (*str && (*str != '=') && c--); )
    *value++ = *str++;
  *value=0;

  if('=' != *str++)
    /* eek, no match */
    return 1;

  if('\"' == *str) {
    /* this starts with a quote so it must end with one as well! */
    str++;
    starts_with_quote = TRUE;
  }

  for(c=MAX_CONTENT_LENGTH-1; *str && c--; str++) {
    switch(*str) {
    case '\\':
      if(!escape) {
        /* possibly the start of an escaped quote */
        escape = TRUE;
        *content++ = '\\'; /* even though this is an escape character, we still
                              store it as-is in the target buffer */
        continue;
      }
      break;
    case ',':
      if(!starts_with_quote) {
        /* this signals the end of the content if we didn't get a starting quote
           and then we do "sloppy" parsing */
        c=0; /* the end */
        continue;
      }
      break;
    case '\r':
    case '\n':
      /* end of string */
      c=0;
      continue;
    case '\"':
      if(!escape && starts_with_quote) {
        /* end of string */
        c=0;
        continue;
      }
      break;
    }
    escape = FALSE;
    *content++ = *str;
  }
  *content=0;

  *endptr = str;

  return 0; /* all is fine! */
}

/* Test example headers:

WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
@@ -90,26 +161,16 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
    Curl_digest_cleanup_one(d);

    while(more) {
      char value[256];
      char content[1024];
      char value[MAX_VALUE_LENGTH];
      char content[MAX_CONTENT_LENGTH];
      size_t totlen=0;

      while(*header && ISSPACE(*header))
        header++;

      /* how big can these strings be? */
      if((2 == sscanf(header, "%255[^=]=\"%1023[^\"]\"",
                      value, content)) ||
         /* try the same scan but without quotes around the content but don't
            include the possibly trailing comma, newline or carriage return */
         (2 ==  sscanf(header, "%255[^=]=%1023[^\r\n,]",
                       value, content)) ) {
        if(!strcmp("\"\"", content)) {
          /* for the name="" case where we get only the "" in the content
           * variable, simply clear the content then
           */
          content[0]=0;
        }
      /* extract a value=content pair */
      if(!get_pair(header, value, content, &header)) {

        if(Curl_raw_equal(value, "nonce")) {
          d->nonce = strdup(content);
          if(!d->nonce)
@@ -185,7 +246,6 @@ CURLdigest Curl_input_digest(struct connectdata *conn,
      else
        break; /* we're done here */

      header += totlen;
      /* pass all additional spaces here */
      while(*header && ISSPACE(*header))
        header++;
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079   \
 test1080 test1081 test1082 test1083 test1084 test1085 test633 test634     \
 test635 test636 test637 test558 test559 test1086 test1087 test1088        \
 test1089 test1090 test1091 test1092 test1093 test1094
 test1089 test1090 test1091 test1092 test1093 test1094 test1095

filecheck:
	@mkdir test-place; \

tests/data/test1095

0 → 100644
+83 −0
Original line number Diff line number Diff line
<testcase>
<info>
<keywords>
HTTP
HTTP GET
HTTP Digest auth
</keywords>
</info>
# Server-side
<reply>
<data>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
WWW-Authenticate: Digest realm="test \"this\" realm!!", nonce="1053604145"
Content-Type: text/html; charset=iso-8859-1
Content-Length: 26

This is not the real page
</data>

# This is supposed to be returned when the server gets a
# Authorization: Digest line passed-in from the client
<data1000>
HTTP/1.1 200 OK swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
Content-Type: text/html; charset=iso-8859-1
Content-Length: 23

This IS the real page!
</data1000>

<datacheck>
HTTP/1.1 401 Authorization Required swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
WWW-Authenticate: Digest realm="test \"this\" realm!!", nonce="1053604145"
Content-Type: text/html; charset=iso-8859-1
Content-Length: 26

HTTP/1.1 200 OK swsclose
Server: Apache/1.3.27 (Darwin) PHP/4.1.2
Content-Type: text/html; charset=iso-8859-1
Content-Length: 23

This IS the real page!
</datacheck>

</reply>

# Client-side
<client>
<server>
http
</server>
<features>
crypto
</features>
 <name>
HTTP with Digest and realm with quoted quotes
 </name>
 <command>
http://%HOSTIP:%HTTPPORT/1095 -u testuser:testpass --digest
</command>
</client>

# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1095 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
Accept: */*

GET /1095 HTTP/1.1
Authorization: Digest username="testuser", realm="test \"this\" realm!!", nonce="1053604145", uri="/1095", response="a1c7931ece9e8617bae2715045e4f49f"
User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 zlib/1.1.3
Host: %HOSTIP:%HTTPPORT
Accept: */*

</protocol>
</verify>
</testcase>