cURL / Mailing Lists / curl-library / Single Mail

curl-library

libCurl not sending basic authentication in 1 out of 300 systems...

From: Paul Bergen <bergen.p0_at_gmail.com>
Date: Fri, 28 Nov 2008 17:31:29 -0800

I wrote c/c++ software that uses libCurl 7.17.1 and runs on a Linux computer
for periodically archiving images from Panasonic cameras. It's really
simple, we just retrieve a given url passing in the username/password for
basic authentication. I've sold 300 systems, and it has run fine on all of
them, until now. On one system, which is otherwise identical to the all the
others, it appears that libCurl is *not* sending the basic authentication
username/password for no apparent reason. The command line utility works
fine, though. I even created a sample app with hardcoded values to be 100%
sure everything is correct. So I'm totally baffled.

This is the command line that works: curl -v -u "dceadmin:dcepass" -o
foo2.jpg "
http://192.168.0.82/low=/SnapshotJPEG?Resolution=320x240&Quality=Standard"
and returns:

> GET /low=/SnapshotJPEG?Resolution=320x240&Quality=Standard HTTP/1.1
> Authorization: Basic ZGNlYWRtaW46ZGNlcGFzcw==
> User-Agent: curl/7.17.1 (mipsel-unknown-linux-gnu) libcurl/7.17.1
OpenSSL/0.9.8h zlib/1.2.3
> Host: 192.168.0.82
> Accept: */*
>
< HTTP/1.0 200 OK
  % Total % Received % Xferd Average Speed Time Time Time
Current
                                 Dload Upload Total Spent Left
Speed
  0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:--
0< Expires: -1
< Cache-Control: no-cache
< Content-length: 14152
< Content-type: image/jpeg
<
{ [data not shown]
100 14152 100 14152 0 0 71887 0 --:--:-- --:--:-- --:--:--
108k

and the resulting foo.jpg is a correct jpg file. If i leave off the -u parm
or change the username/pass, I get a 401. So I know the user/pass are ok.
Now, I do the same thing with libCurl, and this libCurl is the same version
as the command line version, compiled from the same source tree at the same
time, so there should be no difference:

        CURL *curl;
        CURLcode res=CURL_LAST;
        curl = curl_easy_init();
        if(curl)
        {
                curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
char cError[CURL_ERROR_SIZE]="";
curl_easy_setopt ( curl, CURLOPT_ERRORBUFFER, &cError );

                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
curl_write_data); // my own function
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, &cdb); // my own
type of memory manager, not relevent for what's happening
                curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION,
my_curl_debug_callback); // all the debug output
CURLcode c = curl_easy_setopt(curl, CURLOPT_USERPWD, "dceadmin:dcepass");
printf("got %d for userpass", (int) c);
             curl_easy_setopt(curl, CURLOPT_URL, "
http://192.168.0.82/low=/SnapshotJPEG?Resolution=320x240&Quality=Standard");
                curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30); // timeout
                res = curl_easy_perform(curl);
        printf("RES %d c: %s", (int) res, cError);
                curl_easy_cleanup(curl);

now my log function is this:

int my_curl_debug_callback (CURL *pCurl, curl_infotype _curl_infotype, char
*pBuffer, size_t size, void *p_void)
{
        printf("curl_debug_callback for %p with type %d and pvoid %p\n",
pCurl, (int) _curl_infotype, p_void);
        fwrite(pBuffer,1,size,stdout);
        return 0;
}

when I run the code, this is what I get from my printf debugging above

got 0 for userpass
curl_debug_callback for 0x49e1d8 with type 2 and pvoid (nil)
 HTTP/1.1/SnapshotJPEG?Resolution=320x240&Quality=Standard
Authorization: Basic ZGNlYWRtaW46ZGNlcGFzcw==
Host: 192.168.0.82
Accept: */*

curl_debug_callback for 0x49e1d8 with type 3 and pvoid (nil)
<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>
curl_debug_callback for 0x49e1d8 with type 3 and pvoid (nil)
<BODY BGCOLOR="#cc9999"><H2>401 Unauthorized</H2>
<HR>
Authorization required for the requested URL.
</BODY></HTML>
RES 0 c:

and the call to write_function, the output, is this:
<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD>
<BODY BGCOLOR="#cc9999"><H2>401 Unauthorized</H2>
<HR>
Authorization required for the requested URL.
</BODY></HTML>

So, libCurl and the command line both report virtually identical headers.
Both are using the same options. And on 299 out of 300 systems everything
works ok. But, on this one system, for some unknown reason, I keep getting
401 errors from libCurl, as though it's not passing the username and pass.
Since it's only this particular combination of pc + camera that has this
problem, I'd normally swap combinations to debug. But I can't; I'm
debugging this remotely on a customer's location over ssh and he has only
the one camera/pc. So somehow libcurl and curl are doing *something*
different.

I was trying to find a way to get curl and libcurl to report the complete
set of data on the http socket for debug purposes. But it seems neither the
-v on the command line or CURLOPT_DEBUGFUNCTION for libCurl show you
everything because even when it's working from the command line, I can see
that nowhere in the debug output does it show where curl is sending the
username/password for authentication. The term 'dceuser' doesn't even
appear in the output when I run curl -v. So it's not showing me everything
that it's sending.

Any ideas how to increase the verbosity and get the full set of data that
curl/libcurl is sending? Any suggestions for why on this particular system
it seems libCurl isn't sending the basic authentication, when the command
line version is?

Thanks
Received on 2008-11-29