1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#import <KerberosHelper/NetworkAuthenticationHelper.h> 25#import <KerberosHelper/KerberosHelper.h> 26#import <Foundation/Foundation.h> 27#import <Foundation/NSURLConnectionPrivate.h> 28#import <CoreServices/CoreServices.h> 29#import <CoreServices/CoreServicesPriv.h> 30 31#include <err.h> 32 33static NSString *username; 34static NSString *password; 35 36@interface NSURLCredential (NSURLCredentialInternal) 37- (id) _initWithCFURLCredential:(CFURLCredentialRef)credential; 38@end 39 40@interface Foo : NSObject <NSURLConnectionDelegate> { 41 NAHRef _nah; 42 CFArrayRef _selections; 43 CFIndex _selection_index; 44} 45 46- (void)req:(NSURL *)url; 47 48 49 50- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace; 51- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; 52- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; 53- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection; 54 55- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse; 56- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; 57- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; 58- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; 59- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse; 60 61- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 62- (void)connectionDidFinishLoading:(NSURLConnection *)connection; 63 64 65@end 66 67@implementation Foo 68 69 70- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse 71{ 72 return nil; 73} 74 75- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 76{ 77} 78 79 80- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 81{ 82} 83 84- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite 85{ 86} 87 88 89- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 90{ 91 NSLog(@"canAuthenticateAgainstProtectionSpace: %@", [protectionSpace authenticationMethod]); 92 if ([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNegotiate]) 93 return YES; 94 95 return NO; 96} 97 98- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 99 NSLog(@"Connection didReceiveResponse! Response - %@", response); 100} 101- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 102 NSLog(@"Finished..."); 103 exit(0); 104} 105 106- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 107{ 108 NSLog(@"didFailWithError"); 109} 110 111- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse 112{ 113 NSLog(@"willSendRequest"); 114 return request; 115} 116 117- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection 118{ 119 NSLog(@"connectionShouldUseCredentialStorage"); 120 return NO; 121} 122 123 124- (void)connection:(NSURLConnection*)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 125{ 126 NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; 127 128 NSLog(@"didReceiveAuthenticationChallenge: %@ %@", [protectionSpace authenticationMethod], [protectionSpace host]); 129 130 if (_nah == NULL) { 131 CFMutableDictionaryRef info = NULL; 132 CFDictionaryRef krbtoken = NULL; 133 134 info = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 135 136 krbtoken = KRBCreateNegTokenLegacyKerberos(NULL); 137 138 CFDictionaryAddValue(info, kNAHNegTokenInit, krbtoken); 139 CFRelease(krbtoken); 140 141 if (username){ 142 NSLog(@"using %@ as username", username); 143 CFDictionaryAddValue(info, kNAHUserName, username); 144 } 145 146 if (password) 147 CFDictionaryAddValue(info, kNAHPassword, password); 148 149 _nah = NAHCreate(NULL, (CFStringRef)[protectionSpace host], CFSTR("HTTP"), info); 150 if (_nah == NULL) 151 goto failed; 152 153 _selections = NAHGetSelections(_nah); 154 _selection_index = 0; 155 } 156 157 next: 158 if (_selection_index >= CFArrayGetCount(_selections)) 159 goto failed; 160 161 NAHSelectionRef sel = (NAHSelectionRef)CFArrayGetValueAtIndex(_selections, _selection_index); 162 163 _selection_index += 1; 164 165 if (!NAHSelectionAcquireCredential(sel, NULL, NULL)) 166 goto next; 167 168 169 CFStringRef clientPrincipal = NAHSelectionGetInfoForKey(sel, kNAHClientPrincipal); 170 CFStringRef serverPrincipal = NAHSelectionGetInfoForKey(sel, kNAHServerPrincipal); 171 172 NSLog(@"trying: client: %@ server: %@", (NSString *)clientPrincipal, (NSString *)serverPrincipal); 173 174 CFURLCredentialRef cfCredential = _CFURLCredentialCreateForKerberosTicket(NULL, clientPrincipal, serverPrincipal, NULL); 175 if (cfCredential) 176 goto failed; 177 178 NSURLCredential *credential = [[[NSURLCredential alloc] _initWithCFURLCredential:cfCredential] autorelease]; 179 180 [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 181 182 CFRelease(cfCredential); 183 184 return; 185 186 failed: 187 188 [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; 189 190 if (_selections) 191 CFRelease(_selections); 192 if (_nah) 193 CFRelease(_nah); 194 _nah = NULL; 195 _selections = NULL; 196} 197 198 199 200 201 202- (void)req:(NSURL *)url 203{ 204 NSURLRequest *request = [NSURLRequest requestWithURL:url]; 205 NSURLConnection *conn; 206 207 conn = [[NSURLConnection alloc] initWithRequest: request delegate: self]; 208 209 [conn scheduleInRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode]; 210 211} 212 213@end 214 215int 216main(int argc, char **argv) 217{ 218 NSURL *url; 219 Foo *foo; 220 int ch; 221 222 while ((ch = getopt(argc, argv, "u:p:")) != -1) { 223 switch (ch) { 224 case 'u': 225 username = [NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]; 226 break; 227 case 'p': 228 password = [NSString stringWithCString:optarg encoding:NSUTF8StringEncoding]; 229 break; 230 } 231 } 232 233 argv += optind; 234 argc -= optind; 235 236 if (argc < 0) 237 errx(1, "missing url"); 238 239 url = [NSURL URLWithString:[NSString stringWithUTF8String:argv[0]]]; 240 241 foo = [[Foo alloc] init]; 242 243 [foo req: url]; 244 245 [[NSRunLoop currentRunLoop] run]; 246 247 NSLog(@"done"); 248 249 return 0; 250} 251