From dc4270128d3af044ad695a6ccb1f0606b5ca40b4 Mon Sep 17 00:00:00 2001 From: Earl Robsham Date: Fri, 21 Mar 2025 17:24:39 -0400 Subject: [PATCH 1/2] Fix `Authorization` header generation Fixes `Authorization` header generation to include the query parameters (if present). This brings the implementation inline with MacOS, and fixes digest auth with certain picky services. --- ChangeLog | 6 ++++++ Source/GSHTTPURLHandle.m | 24 ++++++++++++++++++++++-- Source/NSURLProtocol.m | 5 ++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7136c3b1a..64226dac0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2025-03-21 Earl Robsham + * Source/GSHTTPURLHandle.m: + * Source/NSURLProtocol.m: + Updates `Authorization` header generation to include the query parameters (if present). + Brings the implementation inline with MacOS. + 2025-03-08 Richard Frith-Macdonald * Headers/GNUstepBase/GSObjCRuntime.h: diff --git a/Source/GSHTTPURLHandle.m b/Source/GSHTTPURLHandle.m index 95ea45b50..91bf1ee48 100644 --- a/Source/GSHTTPURLHandle.m +++ b/Source/GSHTTPURLHandle.m @@ -535,6 +535,7 @@ - (void) bgdApply: (NSString*)basic GSHTTPAuthentication *authentication; NSURLCredential *cred; NSString *method; + NSString *path; /* Create credential from user and password stored in the URL. * Returns nil if we have no username or password. @@ -572,9 +573,18 @@ - (void) bgdApply: (NSString*)basic } } + if ([[u query] length] == 0) + { + path = [u pathWithEscapes]; + } + else + { + path = [NSString stringWithFormat:@"%@?%@", [u pathWithEscapes], [u query]]; + } + auth = [authentication authorizationForAuthentication: nil method: method - path: [u pathWithEscapes]]; + path: path]; /* If authentication is nil then auth will also be nil */ if (auth != nil) @@ -837,6 +847,7 @@ - (void) bgdRead: (NSNotification*) not NSString *ac; GSHTTPAuthentication *authentication; NSString *method; + NSString *path; NSString *auth; ac = [ah value]; @@ -891,9 +902,18 @@ - (void) bgdRead: (NSNotification*) not } } + if ([[url query] length] == 0) + { + path = [url pathWithEscapes]; + } + else + { + path = [NSString stringWithFormat:@"%@?%@", [url pathWithEscapes], [url query]]; + } + auth = [authentication authorizationForAuthentication: ac method: method - path: [url pathWithEscapes]]; + path: path]; if (auth != nil) { [self writeProperty: auth forKey: @"Authorization"]; diff --git a/Source/NSURLProtocol.m b/Source/NSURLProtocol.m index 339cf7873..09a60d346 100644 --- a/Source/NSURLProtocol.m +++ b/Source/NSURLProtocol.m @@ -1413,7 +1413,10 @@ - (void) _got: (NSStream*)stream auth = [authentication authorizationForAuthentication: hdr method: [this->request HTTPMethod] - path: [url pathWithEscapes]]; + path: [[url query] length] == 0 ? + [url pathWithEscapes] : + [NSString stringWithFormat:@"%@?%@", [url pathWithEscapes], [url query]] + ]; } if (auth == nil) From f8173506cd027ca923cd35c0deafb0ed8f3fc065 Mon Sep 17 00:00:00 2001 From: Earl Robsham Date: Tue, 25 Mar 2025 19:40:03 -0400 Subject: [PATCH 2/2] Add `GSDigestURIOmitsQuery` key --- ChangeLog | 3 +++ Headers/Foundation/NSURLHandle.h | 8 ++++++++ Source/GSHTTPURLHandle.m | 8 ++++++-- Source/NSURLProtocol.m | 4 +++- Source/externs.m | 1 + 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64226dac0..6312e59d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,11 @@ 2025-03-21 Earl Robsham + * Headers/Foundation/NSURLHandle.h: + * Sources/externs.m: * Source/GSHTTPURLHandle.m: * Source/NSURLProtocol.m: Updates `Authorization` header generation to include the query parameters (if present). Brings the implementation inline with MacOS. + Also adds the `GSDigestURIOmitsQuery` key for use with ` -[NSHTTPURLHandle writeProperty:forKey:]` / `+[NSURLProtocol setProperty:forKey:inRequest:]` to toggle off this updated behavior. 2025-03-08 Richard Frith-Macdonald diff --git a/Headers/Foundation/NSURLHandle.h b/Headers/Foundation/NSURLHandle.h index 3f37071c8..68bf6250b 100644 --- a/Headers/Foundation/NSURLHandle.h +++ b/Headers/Foundation/NSURLHandle.h @@ -114,6 +114,14 @@ GS_EXPORT NSString * const GSHTTPPropertyKeyFileKey; */ GS_EXPORT NSString * const GSHTTPPropertyPasswordKey; +/** + * Key for passing to [NSURLHandle]'s and [NSHTTPURLProtocol]'s + * propertyForKey.. methods. Specifying @YES will + * signal Digest Authentication logic to always omit the 'query' portion of the + * URI when generating the `Authorization` header. + */ +GS_EXPORT NSString * const GSDigestURIOmitsQuery; + #endif /** diff --git a/Source/GSHTTPURLHandle.m b/Source/GSHTTPURLHandle.m index 91bf1ee48..7e85bb853 100644 --- a/Source/GSHTTPURLHandle.m +++ b/Source/GSHTTPURLHandle.m @@ -536,6 +536,7 @@ - (void) bgdApply: (NSString*)basic NSURLCredential *cred; NSString *method; NSString *path; + NSNumber *omitQuery; /* Create credential from user and password stored in the URL. * Returns nil if we have no username or password. @@ -573,7 +574,8 @@ - (void) bgdApply: (NSString*)basic } } - if ([[u query] length] == 0) + omitQuery = [request objectForKey:GSDigestURIOmitsQuery]; + if ([[u query] length] == 0 || [omitQuery boolValue]) { path = [u pathWithEscapes]; } @@ -849,6 +851,7 @@ - (void) bgdRead: (NSNotification*) not NSString *method; NSString *path; NSString *auth; + NSNumber *omitQuery; ac = [ah value]; space = [GSHTTPAuthentication @@ -902,7 +905,8 @@ - (void) bgdRead: (NSNotification*) not } } - if ([[url query] length] == 0) + omitQuery = [request objectForKey:GSDigestURIOmitsQuery]; + if ([[url query] length] == 0 || [omitQuery boolValue]) { path = [url pathWithEscapes]; } diff --git a/Source/NSURLProtocol.m b/Source/NSURLProtocol.m index 09a60d346..a7ed3a69a 100644 --- a/Source/NSURLProtocol.m +++ b/Source/NSURLProtocol.m @@ -1399,6 +1399,7 @@ - (void) _got: (NSStream*)stream if (_credential != nil) { GSHTTPAuthentication *authentication; + NSNumber *omitQuery; /* Get information about basic or * digest authentication. @@ -1410,10 +1411,11 @@ - (void) _got: (NSStream*)stream /* Generate authentication header value for the * authentication type in the challenge. */ + omitQuery = [this->request _propertyForKey:GSDigestURIOmitsQuery]; auth = [authentication authorizationForAuthentication: hdr method: [this->request HTTPMethod] - path: [[url query] length] == 0 ? + path: [[url query] length] == 0 || [omitQuery boolValue] ? [url pathWithEscapes] : [NSString stringWithFormat:@"%@?%@", [url pathWithEscapes], [url query]] ]; diff --git a/Source/externs.m b/Source/externs.m index 13b558760..abbc6351a 100644 --- a/Source/externs.m +++ b/Source/externs.m @@ -562,6 +562,7 @@ GS_DECLARE NSString* const GSHTTPPropertyCertificateFileKey = @"GSHTTPPropertyCertificateFileKey"; GS_DECLARE NSString* const GSHTTPPropertyKeyFileKey = @"GSHTTPPropertyKeyFileKey"; GS_DECLARE NSString* const GSHTTPPropertyPasswordKey = @"GSHTTPPropertyPasswordKey"; +GS_DECLARE NSString* const GSDigestURIOmitsQuery = @"GSDigestURIOmitsQuery"; /* NSURLProtectionSpace */ GS_DECLARE NSString* const NSURLProtectionSpaceFTPProxy = @"ftp";