cURL / Mailing Lists / curl-library / Single Mail

curl-library

HTTP Post with digest

From: Raf Nulens <raf.nulens_at_androme.com>
Date: Thu, 06 Mar 2008 14:26:54 +0100

Dear all,

we're having an issue with posting binary data when using digest.

This issue already has been reported over a year ago
(http://curl.haxx.se/mail/lib-2007-03/0043.html), but we're still
struggling with it in version 7.18.0.

Problem:

POST /mmas/wbe_302S/wbe.picture.osp HTTP/1.1
Host: 193.166.131.188:8080
Accept: */*
Content-Type: image/png
Content-Length: 0

Instead of waiting for a response from the server, the client starts
immediately sending the binary data!
The client receives a 401 response from the server, but does not retry
the HTTP request with authentication because the binary data
is already being sent.

The following curl options are set:

curl_easy_setopt ( pCURL, CURLOPT_PRIVATE, (void *)pUpload );
curl_easy_setopt ( pCURL, CURLOPT_URL, remotePathName.c_str () );
curl_easy_setopt ( pCURL, CURLOPT_POST, 1 ); curl_easy_setopt (
pCURL, CURLOPT_READDATA, pFile ); curl_easy_setopt ( pCURL,
CURLOPT_POSTFIELDSIZE, fileSize );
curl_easy_setopt ( pCURL, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST );
curl_easy_setopt ( pCURL, CURLOPT_USERPWD, login.c_str () );
curl_easy_setopt ( pCURL, CURLOPT_CAPATH, certificateDirectory );

pCURLList = curl_slist_append ( pCURLList, "Content-Type: image/png" );
curl_easy_setopt ( pCURL, CURLOPT_HTTPHEADER, pCURLList );

This issue can be fixed by reading the full data block before starting
the request (so without using the read callback):

char * pbuffer = new char[fileSize];
fread ( pbuffer, 1, fileSize, pFile );
curl_easy_setopt ( pCURL, CURLOPT_POSTFIELDS, pbuffer );

Problem seems to be that when data is received through the
read-callback, it is immediately sent without checking if authentication
is done.

So to fix this issue we've added an extra test in the readwrite function
in transfer.c:

Line 1403: if((k->keepon & KEEP_WRITE) && (select_res & CURL_CSELECT_OUT)) {

has been replaced by:

if (!conn->data->state.authhost.done &&
(conn->data->state.authhost.picked & CURLAUTH_DIGEST) )
        k->keepon &= ~KEEP_WRITE; /* we're done writing for now */
        /* If we still have writing to do, we check if we have a writable
socket. */
        else if((k->keepon & KEEP_WRITE) && (select_res & CSELECT_OUT) ) {

This seems to solve the issue, we enter the readwrite function again
when the second header (with digest authentication) has been sent.

Note that this issue cannot be reproduced when using easy_perform.

Now our question is: is this the right way to solve the problem?

kind regards,

Raf Nulens
Received on 2008-03-06