Added lock to mediate access to session credentials
Added a couple of comments Add new test to ensure credentials are not reused on a different server
Showing
2 changed files
with
42 additions
and
2 deletions
| @@ -28,9 +28,14 @@ NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; | @@ -28,9 +28,14 @@ NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; | ||
| 28 | 28 | ||
| 29 | static const CFOptionFlags kNetworkEvents = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred; | 29 | static const CFOptionFlags kNetworkEvents = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred; |
| 30 | 30 | ||
| 31 | +// In memory caches of credentials, used on when useSessionPersistance is YES | ||
| 31 | static NSMutableArray *sessionCredentialsStore = nil; | 32 | static NSMutableArray *sessionCredentialsStore = nil; |
| 32 | static NSMutableArray *sessionProxyCredentialsStore = nil; | 33 | static NSMutableArray *sessionProxyCredentialsStore = nil; |
| 33 | 34 | ||
| 35 | +// This lock mediates access to session credentials | ||
| 36 | +static NSRecursiveLock *sessionCredentialsLock = nil; | ||
| 37 | + | ||
| 38 | +// We keep track of cookies we have received here so we can remove them from the sharedHTTPCookieStorage later | ||
| 34 | static NSMutableArray *sessionCookies = nil; | 39 | static NSMutableArray *sessionCookies = nil; |
| 35 | 40 | ||
| 36 | // The number of times we will allow requests to redirect before we fail with a redirection error | 41 | // The number of times we will allow requests to redirect before we fail with a redirection error |
| @@ -2080,6 +2085,9 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | @@ -2080,6 +2085,9 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | ||
| 2080 | if (!sessionProxyCredentialsStore) { | 2085 | if (!sessionProxyCredentialsStore) { |
| 2081 | sessionProxyCredentialsStore = [[NSMutableArray alloc] init]; | 2086 | sessionProxyCredentialsStore = [[NSMutableArray alloc] init]; |
| 2082 | } | 2087 | } |
| 2088 | + if (!sessionCredentialsLock) { | ||
| 2089 | + sessionCredentialsLock = [[NSRecursiveLock alloc] init]; | ||
| 2090 | + } | ||
| 2083 | return sessionProxyCredentialsStore; | 2091 | return sessionProxyCredentialsStore; |
| 2084 | } | 2092 | } |
| 2085 | 2093 | ||
| @@ -2088,66 +2096,84 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | @@ -2088,66 +2096,84 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | ||
| 2088 | if (!sessionCredentialsStore) { | 2096 | if (!sessionCredentialsStore) { |
| 2089 | sessionCredentialsStore = [[NSMutableArray alloc] init]; | 2097 | sessionCredentialsStore = [[NSMutableArray alloc] init]; |
| 2090 | } | 2098 | } |
| 2099 | + if (!sessionCredentialsLock) { | ||
| 2100 | + sessionCredentialsLock = [[NSRecursiveLock alloc] init]; | ||
| 2101 | + } | ||
| 2091 | return sessionCredentialsStore; | 2102 | return sessionCredentialsStore; |
| 2092 | } | 2103 | } |
| 2093 | 2104 | ||
| 2094 | + (void)storeProxyAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials | 2105 | + (void)storeProxyAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials |
| 2095 | { | 2106 | { |
| 2107 | + [sessionCredentialsLock lock]; | ||
| 2096 | [self removeProxyAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@"Credentials"]]; | 2108 | [self removeProxyAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@"Credentials"]]; |
| 2097 | [[[self class] sessionProxyCredentialsStore] addObject:credentials]; | 2109 | [[[self class] sessionProxyCredentialsStore] addObject:credentials]; |
| 2110 | + [sessionCredentialsLock unlock]; | ||
| 2098 | } | 2111 | } |
| 2099 | 2112 | ||
| 2100 | + (void)storeAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials | 2113 | + (void)storeAuthenticationCredentialsInSessionStore:(NSDictionary *)credentials |
| 2101 | { | 2114 | { |
| 2115 | + [sessionCredentialsLock lock]; | ||
| 2102 | [self removeAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@"Credentials"]]; | 2116 | [self removeAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@"Credentials"]]; |
| 2103 | [[[self class] sessionCredentialsStore] addObject:credentials]; | 2117 | [[[self class] sessionCredentialsStore] addObject:credentials]; |
| 2118 | + [sessionCredentialsLock unlock]; | ||
| 2104 | } | 2119 | } |
| 2105 | 2120 | ||
| 2106 | + (void)removeProxyAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials | 2121 | + (void)removeProxyAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials |
| 2107 | { | 2122 | { |
| 2123 | + [sessionCredentialsLock lock]; | ||
| 2108 | NSMutableArray *sessionCredentialsList = [[self class] sessionProxyCredentialsStore]; | 2124 | NSMutableArray *sessionCredentialsList = [[self class] sessionProxyCredentialsStore]; |
| 2109 | int i; | 2125 | int i; |
| 2110 | for (i=0; i<[sessionCredentialsList count]; i++) { | 2126 | for (i=0; i<[sessionCredentialsList count]; i++) { |
| 2111 | NSDictionary *theCredentials = [sessionCredentialsList objectAtIndex:i]; | 2127 | NSDictionary *theCredentials = [sessionCredentialsList objectAtIndex:i]; |
| 2112 | if ([theCredentials objectForKey:@"Credentials"] == credentials) { | 2128 | if ([theCredentials objectForKey:@"Credentials"] == credentials) { |
| 2113 | [sessionCredentialsList removeObjectAtIndex:i]; | 2129 | [sessionCredentialsList removeObjectAtIndex:i]; |
| 2130 | + [sessionCredentialsLock unlock]; | ||
| 2114 | return; | 2131 | return; |
| 2115 | } | 2132 | } |
| 2116 | } | 2133 | } |
| 2134 | + [sessionCredentialsLock unlock]; | ||
| 2117 | } | 2135 | } |
| 2118 | 2136 | ||
| 2119 | + (void)removeAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials | 2137 | + (void)removeAuthenticationCredentialsFromSessionStore:(NSDictionary *)credentials |
| 2120 | { | 2138 | { |
| 2139 | + [sessionCredentialsLock lock]; | ||
| 2121 | NSMutableArray *sessionCredentialsList = [[self class] sessionCredentialsStore]; | 2140 | NSMutableArray *sessionCredentialsList = [[self class] sessionCredentialsStore]; |
| 2122 | int i; | 2141 | int i; |
| 2123 | for (i=0; i<[sessionCredentialsList count]; i++) { | 2142 | for (i=0; i<[sessionCredentialsList count]; i++) { |
| 2124 | NSDictionary *theCredentials = [sessionCredentialsList objectAtIndex:i]; | 2143 | NSDictionary *theCredentials = [sessionCredentialsList objectAtIndex:i]; |
| 2125 | if ([theCredentials objectForKey:@"Credentials"] == credentials) { | 2144 | if ([theCredentials objectForKey:@"Credentials"] == credentials) { |
| 2126 | [sessionCredentialsList removeObjectAtIndex:i]; | 2145 | [sessionCredentialsList removeObjectAtIndex:i]; |
| 2146 | + [sessionCredentialsLock unlock]; | ||
| 2127 | return; | 2147 | return; |
| 2128 | } | 2148 | } |
| 2129 | } | 2149 | } |
| 2150 | + [sessionCredentialsLock unlock]; | ||
| 2130 | } | 2151 | } |
| 2131 | 2152 | ||
| 2132 | - (NSDictionary *)findSessionProxyAuthenticationCredentials | 2153 | - (NSDictionary *)findSessionProxyAuthenticationCredentials |
| 2133 | { | 2154 | { |
| 2155 | + [sessionCredentialsLock lock]; | ||
| 2134 | NSMutableArray *sessionCredentialsList = [[self class] sessionProxyCredentialsStore]; | 2156 | NSMutableArray *sessionCredentialsList = [[self class] sessionProxyCredentialsStore]; |
| 2135 | for (NSDictionary *theCredentials in sessionCredentialsList) { | 2157 | for (NSDictionary *theCredentials in sessionCredentialsList) { |
| 2136 | if ([[theCredentials objectForKey:@"Host"] isEqualTo:[self proxyHost]] && [[theCredentials objectForKey:@"Port"] intValue] == [self proxyPort]) { | 2158 | if ([[theCredentials objectForKey:@"Host"] isEqualTo:[self proxyHost]] && [[theCredentials objectForKey:@"Port"] intValue] == [self proxyPort]) { |
| 2159 | + [sessionCredentialsLock unlock]; | ||
| 2137 | return theCredentials; | 2160 | return theCredentials; |
| 2138 | } | 2161 | } |
| 2139 | } | 2162 | } |
| 2163 | + [sessionCredentialsLock unlock]; | ||
| 2140 | return nil; | 2164 | return nil; |
| 2141 | } | 2165 | } |
| 2142 | 2166 | ||
| 2143 | 2167 | ||
| 2144 | - (NSDictionary *)findSessionAuthenticationCredentials | 2168 | - (NSDictionary *)findSessionAuthenticationCredentials |
| 2145 | { | 2169 | { |
| 2170 | + [sessionCredentialsLock lock]; | ||
| 2146 | NSMutableArray *sessionCredentialsList = [[self class] sessionCredentialsStore]; | 2171 | NSMutableArray *sessionCredentialsList = [[self class] sessionCredentialsStore]; |
| 2147 | // Find an exact match | 2172 | // Find an exact match |
| 2148 | for (NSDictionary *theCredentials in sessionCredentialsList) { | 2173 | for (NSDictionary *theCredentials in sessionCredentialsList) { |
| 2149 | if ([[theCredentials objectForKey:@"URL"] isEqualTo:[self url]]) { | 2174 | if ([[theCredentials objectForKey:@"URL"] isEqualTo:[self url]]) { |
| 2150 | if (![self responseStatusCode] || [[theCredentials objectForKey:@"AuthenticationRealm"] isEqualTo:[self authenticationRealm]]) { | 2175 | if (![self responseStatusCode] || [[theCredentials objectForKey:@"AuthenticationRealm"] isEqualTo:[self authenticationRealm]]) { |
| 2176 | + [sessionCredentialsLock unlock]; | ||
| 2151 | return theCredentials; | 2177 | return theCredentials; |
| 2152 | } | 2178 | } |
| 2153 | } | 2179 | } |
| @@ -2158,10 +2184,12 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | @@ -2158,10 +2184,12 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | ||
| 2158 | NSURL *theURL = [theCredentials objectForKey:@"URL"]; | 2184 | NSURL *theURL = [theCredentials objectForKey:@"URL"]; |
| 2159 | if ([[theURL host] isEqualTo:[requestURL host]] && [[theURL port] isEqualTo:[requestURL port]] && [[theURL scheme] isEqualTo:[requestURL scheme]]) { | 2185 | if ([[theURL host] isEqualTo:[requestURL host]] && [[theURL port] isEqualTo:[requestURL port]] && [[theURL scheme] isEqualTo:[requestURL scheme]]) { |
| 2160 | if (![self responseStatusCode] || [[theCredentials objectForKey:@"AuthenticationRealm"] isEqualTo:[self authenticationRealm]]) { | 2186 | if (![self responseStatusCode] || [[theCredentials objectForKey:@"AuthenticationRealm"] isEqualTo:[self authenticationRealm]]) { |
| 2187 | + [sessionCredentialsLock unlock]; | ||
| 2161 | return theCredentials; | 2188 | return theCredentials; |
| 2162 | } | 2189 | } |
| 2163 | } | 2190 | } |
| 2164 | } | 2191 | } |
| 2192 | + [sessionCredentialsLock unlock]; | ||
| 2165 | return nil; | 2193 | return nil; |
| 2166 | } | 2194 | } |
| 2167 | 2195 | ||
| @@ -2250,7 +2278,7 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | @@ -2250,7 +2278,7 @@ static NSRecursiveLock *delegateAuthenticationLock = nil; | ||
| 2250 | + (void)clearSession | 2278 | + (void)clearSession |
| 2251 | { | 2279 | { |
| 2252 | [[[self class] sessionCredentialsStore] removeAllObjects]; | 2280 | [[[self class] sessionCredentialsStore] removeAllObjects]; |
| 2253 | - [ASIHTTPRequest setSessionCookies:nil]; | 2281 | + [[self class] setSessionCookies:nil]; |
| 2254 | } | 2282 | } |
| 2255 | 2283 | ||
| 2256 | #pragma mark gzip decompression | 2284 | #pragma mark gzip decompression |
| @@ -456,8 +456,9 @@ | @@ -456,8 +456,9 @@ | ||
| 456 | 456 | ||
| 457 | - (void)testBasicAuthentication | 457 | - (void)testBasicAuthentication |
| 458 | { | 458 | { |
| 459 | + [ASIHTTPRequest clearSession]; | ||
| 459 | 460 | ||
| 460 | - NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"] autorelease]; | 461 | + NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"]; |
| 461 | ASIHTTPRequest *request; | 462 | ASIHTTPRequest *request; |
| 462 | BOOL success; | 463 | BOOL success; |
| 463 | NSError *err; | 464 | NSError *err; |
| @@ -514,6 +515,17 @@ | @@ -514,6 +515,17 @@ | ||
| 514 | [request start]; | 515 | [request start]; |
| 515 | err = [request error]; | 516 | err = [request error]; |
| 516 | GHAssertNil(err,@"Failed to use stored credentials"); | 517 | GHAssertNil(err,@"Failed to use stored credentials"); |
| 518 | + | ||
| 519 | + // Ok, now let's test on a different server | ||
| 520 | + url = [NSURL URLWithString:@"https://selfsigned.allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"]; | ||
| 521 | + request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; | ||
| 522 | + [request setUseSessionPersistance:YES]; | ||
| 523 | + [request setUseKeychainPersistance:NO]; | ||
| 524 | + [request setValidatesSecureCertificate:NO]; | ||
| 525 | + [request start]; | ||
| 526 | + success = [[request error] code] == ASIAuthenticationErrorType; | ||
| 527 | + GHAssertTrue(success,@"Reused credentials when we shouldn't have"); | ||
| 528 | + | ||
| 517 | } | 529 | } |
| 518 | 530 | ||
| 519 | 531 |
-
Please register or login to post a comment