[prev in list] [next in list] [prev in thread] [next in thread]
List: kfm-devel
Subject: PATCH: Fix elusive HTTP digest authentication problem (BR# 42604)
From: "Dawit A." <adawit () kde ! org>
Date: 2002-12-07 6:13:48
[Download RAW message or body]
Hi,
Attached are patches for both HEAD and 3_1_BRANCH that fixes an elusive HTTP
digest authentication bug that was first reported by BR# 42604. As luck
would have it, I run into this bug myself when attempting to log into a
digest authentication protected website at work.
The problem stemmed from incorrect setting of the uri= parameter in the
Authentication line. While I was fixing that I also opted to complete the
proper credential verification for preemptively sending the
authentication-digest line to the server based on the "domain=" attribute
extracted from a 401/407 response.
Anyways, this fixes the problem as verified against my own test apache server.
Regards,
Dawit A.
["http_digest_31.patch" (text/x-diff)]
? .http.cc.swp
Index: http.cc
===================================================================
RCS file: /home/kde/kdelibs/kioslave/http/http.cc,v
retrieving revision 1.470.2.19
diff -u -p -b -B -w -r1.470.2.19 http.cc
--- http.cc 3 Dec 2002 05:45:20 -0000 1.470.2.19
+++ http.cc 7 Dec 2002 05:50:19 -0000
@@ -1903,6 +1903,9 @@ bool HTTPProtocol::httpOpen()
davHeader = "Lock-token: " + metaData("davLockToken") + "\r\n";
m_bCachedWrite = false; // Do not put any result in the cache
break;
+ default:
+ error (ERR_UNSUPPORTED_ACTION, QString::null);
+ return false;
}
if ( isSSLTunnelEnabled() )
@@ -2097,11 +2100,9 @@ bool HTTPProtocol::httpOpen()
{
case AUTH_Basic:
header += createBasicAuth();
- header += "\r\n";
break;
case AUTH_Digest:
header += createDigestAuth();
- header += "\r\n";
break;
case AUTH_None:
default:
@@ -4702,6 +4703,8 @@ QString HTTPProtocol::createBasicAuth( b
user += ':';
user += passwd;
auth += KCodecs::base64Encode( user );
+ auth += "\r\n";
+
return auth;
}
@@ -4731,12 +4734,12 @@ void HTTPProtocol::calculateResponse( Di
}
HA1 = md.hexDigest();
- kdDebug(7113) << "(" << m_pid << ") A1 => " << HA1 << endl;
+ kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A1 => " << HA1 << endl;
// Calcualte H(A2)
authStr = info.method;
authStr += ':';
- authStr += info.digestURI.at( 0 );
+ authStr += m_request.url.encodedPathAndQuery(0, true).latin1();
if ( info.qop == "auth-int" )
{
authStr += ':';
@@ -4746,7 +4749,8 @@ void HTTPProtocol::calculateResponse( Di
md.update( authStr );
HA2 = md.hexDigest();
- kdDebug(7113) << "(" << m_pid << ") A2 => " << HA2 << endl;
+ kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A2 => "
+ << HA2 << endl;
// Calcualte the response.
authStr = HA1;
@@ -4767,7 +4771,8 @@ void HTTPProtocol::calculateResponse( Di
md.update( authStr );
Response = md.hexDigest();
- kdDebug(7113) << "(" << m_pid << ") Response => " << Response << endl;
+ kdDebug(7113) << "(" << m_pid << ") calculateResponse(): Response => "
+ << Response << endl;
}
QString HTTPProtocol::createDigestAuth ( bool isForProxy )
@@ -4871,9 +4876,17 @@ QString HTTPProtocol::createDigestAuth (
{
pos = uri.find( ',', pos );
if ( pos != -1 )
- info.digestURI.append( uri.mid(idx, pos-idx) );
+ {
+ KURL u (m_request.url, uri.mid(idx, pos-idx));
+ if (!u.isMalformed ())
+ info.digestURI.append( u.url().latin1() );
+ }
else
- info.digestURI.append( uri.mid(idx, uri.length()-idx) );
+ {
+ KURL u (m_request.url, uri.mid(idx, uri.length()-idx));
+ if (!u.isMalformed ())
+ info.digestURI.append( u.url().latin1() );
+ }
idx = pos+1;
} while ( pos != -1 );
}
@@ -4901,8 +4914,50 @@ QString HTTPProtocol::createDigestAuth (
p+=(i+1);
}
- if ( info.digestURI.isEmpty() )
- info.digestURI.append( m_request.path.latin1() );
+ // If the "domain" attribute was not specified and the current response code
+ // is authentication needed, add the current request url to the list over which
+ // this credential can be automatically applied.
+ if (info.digestURI.isEmpty() && (m_responseCode == 401 || m_responseCode == 407))
+ info.digestURI.append (m_request.url.url().latin1());
+ else
+ {
+ // Verify whether or not we should send a cached credential to the
+ // server based on the stored "domain" attribute...
+ bool send = true;
+
+ // Determine the path of the request url...
+ QString requestPath = m_request.url.directory(false, false);
+ if (requestPath.isEmpty())
+ requestPath = "/";
+
+ int count = info.digestURI.count();
+
+ for (int i = 0; i < count; i++ )
+ {
+ KURL u = info.digestURI.at(i);
+
+ send &= (m_request.url.protocol().lower() == u.protocol().lower());
+ send &= (m_request.hostname.lower() == u.host().lower());
+
+ if (m_request.port > 0 && u.port() > 0)
+ send &= (m_request.port == u.port());
+
+ QString digestPath = u.directory (false, false);
+ if (digestPath.isEmpty())
+ digestPath = "/";
+
+ send &= (requestPath.startsWith(digestPath));
+
+ if (send)
+ break;
+ }
+
+ kdDebug(7113) << "(" << m_pid << ") createDigestAuth(): passed digest "
+ "authentication credential test: " << send << endl;
+
+ if (!send)
+ return QString::null;
+ }
kdDebug(7113) << "(" << m_pid << ") RESULT OF PARSING:" << endl;
kdDebug(7113) << "(" << m_pid << ") algorithm: " << info.algorithm << endl;
@@ -4911,11 +4966,6 @@ QString HTTPProtocol::createDigestAuth (
kdDebug(7113) << "(" << m_pid << ") opaque: " << opaque << endl;
kdDebug(7113) << "(" << m_pid << ") qop: " << info.qop << endl;
- int count = info.digestURI.count();
- for( int i = 0; i < count; i++ )
- kdDebug(7113) << "(" << m_pid << ") domain[" << i << "]: "
- << info.digestURI.at(i) << endl;
-
// Calculate the response...
calculateResponse( info, Response );
@@ -4930,7 +4980,7 @@ QString HTTPProtocol::createDigestAuth (
auth += info.nonce;
auth += "\", uri=\"";
- auth += info.digestURI.at(0);
+ auth += m_request.url.encodedPathAndQuery(0, true);
auth += "\", algorithm=\"";
auth += info.algorithm;
@@ -4953,9 +5003,8 @@ QString HTTPProtocol::createDigestAuth (
auth += "\", opaque=\"";
auth += opaque;
}
- auth += "\"";
+ auth += "\"\r\n";
- kdDebug(7113) << "(" << m_pid << ") Digest header: " << auth << endl;
return auth;
}
@@ -5021,11 +5070,9 @@ QString HTTPProtocol::proxyAuthenticatio
{
case AUTH_Basic:
header += createBasicAuth( true );
- header += "\r\n";
break;
case AUTH_Digest:
header += createDigestAuth( true );
- header += "\r\n";
break;
case AUTH_None:
default:
["http_digest_head.patch" (text/x-diff)]
Index: http.cc
===================================================================
RCS file: /home/kde/kdelibs/kioslave/http/http.cc,v
retrieving revision 1.555
diff -u -p -b -B -w -r1.555 http.cc
--- http.cc 2 Dec 2002 12:59:47 -0000 1.555
+++ http.cc 7 Dec 2002 05:51:13 -0000
@@ -1967,10 +1967,12 @@ bool HTTPProtocol::httpOpen()
header = "PROPFIND ";
davData = true;
davHeader = "Depth: ";
- if ( hasMetaData( "davDepth" ) ) {
+ if ( hasMetaData( "davDepth" ) )
+ {
kdDebug(7113) << "Reading DAV depth from metadata: " << metaData( "davDepth" ) << endl;
davHeader += metaData( "davDepth" );
- } else
+ }
+ else
{
if ( m_request.davData.depth == 2 )
davHeader += "infinity";
@@ -2038,7 +2040,7 @@ bool HTTPProtocol::httpOpen()
header = "POLL ";
m_request.bCachedWrite = false;
break;
- case HTTP_UNKNOWN:
+ default:
error (ERR_UNSUPPORTED_ACTION, QString::null);
return false;
}
@@ -2256,11 +2258,9 @@ bool HTTPProtocol::httpOpen()
{
case AUTH_Basic:
header += createBasicAuth();
- header += "\r\n";
break;
case AUTH_Digest:
header += createDigestAuth();
- header += "\r\n";
break;
case AUTH_None:
default:
@@ -4940,6 +4940,8 @@ QString HTTPProtocol::createBasicAuth( b
user += ':';
user += passwd;
auth += KCodecs::base64Encode( user );
+ auth += "\r\n";
+
return auth;
}
@@ -4969,12 +4971,12 @@ void HTTPProtocol::calculateResponse( Di
}
HA1 = md.hexDigest();
- kdDebug(7113) << "(" << m_pid << ") A1 => " << HA1 << endl;
+ kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A1 => " << HA1 << endl;
// Calcualte H(A2)
authStr = info.method;
authStr += ':';
- authStr += info.digestURI.at( 0 );
+ authStr += m_request.url.encodedPathAndQuery(0, true).latin1();
if ( info.qop == "auth-int" )
{
authStr += ':';
@@ -4984,7 +4986,8 @@ void HTTPProtocol::calculateResponse( Di
md.update( authStr );
HA2 = md.hexDigest();
- kdDebug(7113) << "(" << m_pid << ") A2 => " << HA2 << endl;
+ kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A2 => "
+ << HA2 << endl;
// Calcualte the response.
authStr = HA1;
@@ -5005,7 +5008,8 @@ void HTTPProtocol::calculateResponse( Di
md.update( authStr );
Response = md.hexDigest();
- kdDebug(7113) << "(" << m_pid << ") Response => " << Response << endl;
+ kdDebug(7113) << "(" << m_pid << ") calculateResponse(): Response => "
+ << Response << endl;
}
QString HTTPProtocol::createDigestAuth ( bool isForProxy )
@@ -5110,9 +5114,17 @@ QString HTTPProtocol::createDigestAuth (
{
pos = uri.find( ',', pos );
if ( pos != -1 )
- info.digestURI.append( uri.mid(idx, pos-idx) );
+ {
+ KURL u (m_request.url, uri.mid(idx, pos-idx));
+ if (!u.isMalformed ())
+ info.digestURI.append( u.url().latin1() );
+ }
else
- info.digestURI.append( uri.mid(idx, uri.length()-idx) );
+ {
+ KURL u (m_request.url, uri.mid(idx, uri.length()-idx));
+ if (!u.isMalformed ())
+ info.digestURI.append( u.url().latin1() );
+ }
idx = pos+1;
} while ( pos != -1 );
}
@@ -5140,8 +5152,50 @@ QString HTTPProtocol::createDigestAuth (
p+=(i+1);
}
- if ( info.digestURI.isEmpty() )
- info.digestURI.append( m_request.path.latin1() );
+ // If the "domain" attribute was not specified and the current response code
+ // is authentication needed, add the current request url to the list over which
+ // this credential can be automatically applied.
+ if (info.digestURI.isEmpty() && (m_responseCode == 401 || m_responseCode == 407))
+ info.digestURI.append (m_request.url.url().latin1());
+ else
+ {
+ // Verify whether or not we should send a cached credential to the
+ // server based on the stored "domain" attribute...
+ bool send = true;
+
+ // Determine the path of the request url...
+ QString requestPath = m_request.url.directory(false, false);
+ if (requestPath.isEmpty())
+ requestPath = "/";
+
+ int count = info.digestURI.count();
+
+ for (int i = 0; i < count; i++ )
+ {
+ KURL u = info.digestURI.at(i);
+
+ send &= (m_request.url.protocol().lower() == u.protocol().lower());
+ send &= (m_request.hostname.lower() == u.host().lower());
+
+ if (m_request.port > 0 && u.port() > 0)
+ send &= (m_request.port == u.port());
+
+ QString digestPath = u.directory (false, false);
+ if (digestPath.isEmpty())
+ digestPath = "/";
+
+ send &= (requestPath.startsWith(digestPath));
+
+ if (send)
+ break;
+ }
+
+ kdDebug(7113) << "(" << m_pid << ") createDigestAuth(): passed digest "
+ "authentication credential test: " << send << endl;
+
+ if (!send)
+ return QString::null;
+ }
kdDebug(7113) << "(" << m_pid << ") RESULT OF PARSING:" << endl;
kdDebug(7113) << "(" << m_pid << ") algorithm: " << info.algorithm << endl;
@@ -5150,11 +5204,6 @@ QString HTTPProtocol::createDigestAuth (
kdDebug(7113) << "(" << m_pid << ") opaque: " << opaque << endl;
kdDebug(7113) << "(" << m_pid << ") qop: " << info.qop << endl;
- int count = info.digestURI.count();
- for( int i = 0; i < count; i++ )
- kdDebug(7113) << "(" << m_pid << ") domain[" << i << "]: "
- << info.digestURI.at(i) << endl;
-
// Calculate the response...
calculateResponse( info, Response );
@@ -5169,7 +5218,7 @@ QString HTTPProtocol::createDigestAuth (
auth += info.nonce;
auth += "\", uri=\"";
- auth += info.digestURI.at(0);
+ auth += m_request.url.encodedPathAndQuery(0, true);
auth += "\", algorithm=\"";
auth += info.algorithm;
@@ -5192,9 +5241,8 @@ QString HTTPProtocol::createDigestAuth (
auth += "\", opaque=\"";
auth += opaque;
}
- auth += "\"";
+ auth += "\"\r\n";
- kdDebug(7113) << "(" << m_pid << ") Digest header: " << auth << endl;
return auth;
}
@@ -5259,11 +5307,9 @@ QString HTTPProtocol::proxyAuthenticatio
{
case AUTH_Basic:
header += createBasicAuth( true );
- header += "\r\n";
break;
case AUTH_Digest:
header += createDigestAuth( true );
- header += "\r\n";
break;
case AUTH_None:
default:
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic