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
44 additions
and
4 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