]> git.saurik.com Git - apple/security.git/blob - tests/TrustTests/TrustEvaluationTestHelpers.m
Security-59754.80.3.tar.gz
[apple/security.git] / tests / TrustTests / TrustEvaluationTestHelpers.m
1 //
2 // TrustEvaluationTestHelpers.m
3 // Security
4 //
5 //
6
7 #include <AssertMacros.h>
8 #import <Foundation/Foundation.h>
9 #import <Security/Security.h>
10
11 #include <utilities/SecInternalReleasePriv.h>
12 #include <utilities/SecCFRelease.h>
13 #include <utilities/SecCFWrappers.h>
14 #include <Security/SecCertificate.h>
15 #include <Security/SecCertificatePriv.h>
16 #include <Security/SecPolicyPriv.h>
17 #include <Security/SecTrust.h>
18 #include <Security/SecTrustPriv.h>
19 #include <stdlib.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <netdb.h>
25 #include <unistd.h>
26 #include <string.h>
27
28 #include "TrustEvaluationTestHelpers.h"
29
30 // Want a class for running trust evaluations
31 // Want a dictionary-driven test with callback
32
33 @interface TestTrustEvaluation ()
34 @property NSString *directory;
35 @property NSMutableArray *certificates;
36 @property NSMutableArray *policies;
37 @property BOOL enableTestCertificates;
38 @end
39
40 @implementation TestTrustEvaluation
41 @synthesize ocspResponses = _ocspResponses;
42 @synthesize presentedSCTs = _presentedSCTs;
43 @synthesize trustedCTLogs = _trustedCTLogs;
44
45
46 - (instancetype)initWithCertificates:(NSArray *)certs policies:(NSArray *)policies {
47 if (self = [super init]) {
48 if (errSecSuccess != SecTrustCreateWithCertificates((__bridge CFArrayRef)certs, (__bridge CFArrayRef)policies, &_trust)) {
49 return NULL;
50 }
51 }
52 return self;
53 }
54
55 - (void)addAnchor:(SecCertificateRef)certificate
56 {
57 CFArrayRef anchors = NULL;
58 SecTrustCopyCustomAnchorCertificates(_trust, &anchors);
59
60 NSMutableArray *newAnchors = [NSMutableArray array];
61 if (anchors) {
62 [newAnchors addObjectsFromArray:CFBridgingRelease(anchors)];
63 }
64 [newAnchors addObject:(__bridge id)certificate];
65 (void)SecTrustSetAnchorCertificates(_trust, (__bridge CFArrayRef)newAnchors);
66 }
67
68 - (void)setAnchors:(NSArray *)anchorArray {
69 (void)SecTrustSetAnchorCertificates(_trust, (__bridge CFArrayRef)anchorArray);
70 }
71
72 - (NSArray *)anchors {
73 CFArrayRef anchors = NULL;
74 SecTrustCopyCustomAnchorCertificates(_trust, &anchors);
75 return CFBridgingRelease(anchors);
76 }
77
78 - (void)setOcspResponses:(NSArray *)ocspResponsesArray {
79 if (ocspResponsesArray != _ocspResponses) {
80 _ocspResponses = nil;
81 _ocspResponses = ocspResponsesArray;
82 (void)SecTrustSetOCSPResponse(_trust, (__bridge CFArrayRef)ocspResponsesArray);
83 }
84 }
85
86 - (void)setPresentedSCTs:(NSArray *)presentedSCTsArray {
87 if (presentedSCTsArray != _presentedSCTs) {
88 _presentedSCTs = nil;
89 _presentedSCTs = presentedSCTsArray;
90 (void)SecTrustSetSignedCertificateTimestamps(_trust, (__bridge CFArrayRef)presentedSCTsArray);
91 }
92 }
93
94 - (void)setTrustedCTLogs:(NSArray *)trustedCTLogsArray {
95 if (trustedCTLogsArray != _trustedCTLogs) {
96 _trustedCTLogs = nil;
97 _trustedCTLogs = trustedCTLogsArray;
98 (void)SecTrustSetTrustedLogs(_trust, (__bridge CFArrayRef)trustedCTLogsArray);
99 }
100 }
101
102 - (void)setVerifyDate:(NSDate *)aVerifyDate {
103 if (aVerifyDate != _verifyDate) {
104 _verifyDate = nil;
105 _verifyDate = aVerifyDate;
106 (void)SecTrustSetVerifyDate(_trust, (__bridge CFDateRef)aVerifyDate);
107 }
108 }
109
110 - (void)setNeedsEvaluation {
111 SecTrustSetNeedsEvaluation(_trust);
112 }
113
114 - (bool)evaluate:(out NSError * _Nullable __autoreleasing *)outError {
115 CFErrorRef localError = nil;
116 _trustResult = kSecTrustResultInvalid;
117 _resultDictionary = nil;
118 bool result = SecTrustEvaluateWithError(_trust, &localError);
119 if (outError && localError) {
120 *outError = CFBridgingRelease(localError);
121 }
122 (void)SecTrustGetTrustResult(_trust, &_trustResult);
123 _resultDictionary = CFBridgingRelease(SecTrustCopyResult(_trust));
124 return result;
125 }
126
127 - (void) dealloc {
128 CFReleaseNull(_trust);
129 }
130
131 /* MARK: -
132 * MARK: Dictionary-driven trust objects
133 */
134
135 /* INSTRUCTIONS FOR ADDING NEW DICTIONARY-DRIVEN TRUSTS:
136 * 1. Add the certificates, as DER-encoded files with the 'cer' extension to a directory included in the test Resources
137 * (e.g. OSX/shared_regressions/si-20-sectrust-policies-data/)
138 * NOTE: If your cert needs to be named with "(i[Pp]hone|i[Pp]ad|i[Pp]od)", you need to make two copies -- one named properly
139 * and another named such that it doesn't match that regex. Use the regex trick below for TARGET_OS_TV to make sure your test
140 * works.
141 * 2. The input dictionary must include: (see constants below)
142 * MajorTestName
143 * MinorTestName
144 * Policies
145 * Leaf
146 * ExpectedResult
147 * CertDirectory
148 * It is strongly recommended that all test dictionaries include the Anchors and VerifyDate keys.
149 * Addtional optional keys are defined below.
150 */
151
152 /* Key Constants for Test Dictionaries */
153 const NSString *kSecTrustTestMajorTestName = @"MajorTestName"; /* Required; value: string */
154 const NSString *kSecTrustTestMinorTestName = @"MinorTestName"; /* Required; value: string */
155 const NSString *kSecTrustTestPolicies = @"Policies"; /* Required; value: dictionary or array of dictionaries */
156 const NSString *kSecTrustTestLeaf = @"Leaf"; /* Required; value: string */
157 const NSString *kSecTrustTestIntermediates = @"Intermediates"; /* Optional; value: string or array of strings */
158 const NSString *kSecTrustTestAnchors = @"Anchors"; /* Recommended; value: string or array of strings */
159 const NSString *kSecTrustTestVerifyDate = @"VerifyDate"; /* Recommended; value: date */
160 const NSString *kSecTrustTestExpectedResult = @"ExpectedResult"; /* Required; value: number */
161 const NSString *kSecTrustTestChainLength = @"ChainLength"; /* Optional; value: number */
162 const NSString *kSecTrustTestEnableTestCerts= @"EnableTestCertificates"; /* Optional; value: string */
163 const NSString *kSecTrustTestDisableBridgeOS= @"BridgeOSDisable"; /* Optional; value: boolean */
164 const NSString *kSecTrustTestDirectory = @"CertDirectory"; /* Required; value: string */
165
166 /* Key Constants for Policies Dictionaries */
167 const NSString *kSecTrustTestPolicyOID = @"PolicyIdentifier"; /* Required; value: string */
168 const NSString *kSecTrustTestPolicyProperties = @"Properties"; /* Optional; value: dictionary, see Policy Value Constants, SecPolicy.h */
169
170 - (void)setMajorTestName:(NSString *)majorTestName minorTestName:(NSString *)minorTestName {
171 self.fullTestName = [[majorTestName stringByAppendingString:@"-"] stringByAppendingString:minorTestName];
172 }
173
174 #if TARGET_OS_TV
175 /* Mastering removes all files named i[Pp]hone, so dynamically replace any i[Pp]hone's with
176 * iPh0ne. We have two copies in the resources directory. */
177 - (NSString *)replaceiPhoneNamedFiles:(NSString *)filename {
178 NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:@"iphone"
179 options:NSRegularExpressionCaseInsensitive
180 error:nil];
181 NSString *newfilename = [regularExpression stringByReplacingMatchesInString:filename
182 options:0
183 range:NSMakeRange(0, [filename length])
184 withTemplate:@"iPh0ne"];
185 return newfilename;
186 }
187 #endif
188
189 - (bool)addLeafToCertificates:(NSString *)leafName {
190 SecCertificateRef cert;
191 NSString *path = nil, *filename = nil;
192 require_string(leafName, errOut, "%@: failed to get leaf for test");
193 #if TARGET_OS_TV
194 filename = [self replaceiPhoneNamedFiles:leafName];
195 #else
196 filename = leafName;
197 #endif
198
199 path = [[NSBundle bundleForClass:[self class]]
200 pathForResource:filename
201 ofType:@"cer"
202 inDirectory:self.directory];
203 require_string(path, errOut, "failed to get path for leaf");
204 cert = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
205 require_string(cert, errOut, "failed to create leaf certificate from path");
206 self.certificates = [[NSMutableArray alloc] initWithObjects:(__bridge id)cert, nil];
207 CFReleaseNull(cert);
208 require_string(self.certificates, errOut, "failed to initialize certificates array");
209 return true;
210
211 errOut:
212 return false;
213 }
214
215 - (bool)addCertsToArray:(id)pathsObj outputArray:(NSMutableArray *)outArray {
216 __block SecCertificateRef cert = NULL;
217 __block NSString* path = nil, *filename = nil;
218 require_string(pathsObj, errOut,
219 "failed to get certificate paths for test");
220
221 if ([pathsObj isKindOfClass:[NSString class]]) {
222 /* Only one cert path */
223 #if TARGET_OS_TV
224 filename = [self replaceiPhoneNamedFiles:pathsObj];
225 #else
226 filename = pathsObj;
227 #endif
228 path = [[NSBundle bundleForClass:[self class]]
229 pathForResource:filename
230 ofType:@"cer"
231 inDirectory:self.directory];
232 require_string(path, errOut, "failed to get path for cert");
233 cert = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
234 require_string(cert, errOut, "failed to create certificate from path");
235 [outArray addObject:(__bridge id)cert];
236 CFReleaseNull(cert);
237 } else if ([pathsObj isKindOfClass:[NSArray class]]) {
238 /* Test has more than one intermediate */
239 [(NSArray *)pathsObj enumerateObjectsUsingBlock:^(NSString *resource, NSUInteger idx, BOOL *stop) {
240 #if TARGET_OS_TV
241 filename = [self replaceiPhoneNamedFiles:resource];
242 #else
243 filename = resource;
244 #endif
245 path = [[NSBundle bundleForClass:[self class]]
246 pathForResource:filename
247 ofType:@"cer"
248 inDirectory:self.directory];
249 require_string(path, blockOut, "failed to get path for cert");
250 cert = SecCertificateCreateWithData(NULL, (CFDataRef)[NSData dataWithContentsOfFile:path]);
251 require_string(cert, blockOut, "failed to create certificate %ld from path %@");
252 [outArray addObject:(__bridge id)cert];
253
254 CFReleaseNull(cert);
255 return;
256
257 blockOut:
258 CFReleaseNull(cert);
259 *stop = YES;
260 }];
261 } else {
262 require_string(false, errOut, "unexpected type for intermediates or anchors value");
263 }
264
265 return true;
266
267 errOut:
268 CFReleaseNull(cert);
269 return false;
270 }
271
272 - (bool)addIntermediatesToCertificates:(id)intermediatesObj {
273 require_string(intermediatesObj, errOut, "failed to get intermediates for test");
274
275 require_string([self addCertsToArray:intermediatesObj outputArray:self.certificates], errOut,
276 "failed to add intermediates to certificates array");
277
278 if ([intermediatesObj isKindOfClass:[NSString class]]) {
279 require_string([self.certificates count] == 2, errOut,
280 "failed to add all intermediates");
281 } else if ([intermediatesObj isKindOfClass:[NSArray class]]) {
282 require_string([self.certificates count] == [(NSArray *)intermediatesObj count] + 1, errOut,
283 "failed to add all intermediates");
284 }
285
286 return true;
287
288 errOut:
289 return false;
290 }
291
292 - (bool)addThirdPartyPinningPolicyChecks:(CFDictionaryRef)properties
293 policy:(SecPolicyRef)policy
294 {
295 if (!properties) {
296 return true;
297 }
298
299 CFStringRef spkiSHA256Options[] = {
300 kSecPolicyCheckLeafSPKISHA256,
301 kSecPolicyCheckCAspkiSHA256,
302 };
303
304 for (size_t i = 0; i < sizeof(spkiSHA256Options)/sizeof(spkiSHA256Options[0]); i++) {
305 CFArrayRef spkiSHA256StringArray = CFDictionaryGetValue(properties, spkiSHA256Options[i]);
306 // Relevant property is not set.
307 if (!spkiSHA256StringArray) {
308 continue;
309 }
310 require_string(isArray(spkiSHA256StringArray), errOut, "SPKISHA256 property is not an array");
311
312 CFMutableArrayRef spkiSHA256DataArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
313 require_string(spkiSHA256DataArray, errOut, "failed to allocate memory for the SPKISHA256 data array");
314
315 for (CFIndex j = 0; j < CFArrayGetCount(spkiSHA256StringArray); j++) {
316 CFStringRef spkiSHA256String = CFArrayGetValueAtIndex(spkiSHA256StringArray, j);
317 require_string(isString(spkiSHA256String), errOut, "SPKISHA256 property array element is not a string");
318 CFDataRef spkiSHA256Data = CreateCFDataFromBase64CFString(spkiSHA256String);
319 // 'spkiSHA256Data' is optional because we want to allow empty strings.
320 if (spkiSHA256Data) {
321 CFArrayAppendValue(spkiSHA256DataArray, spkiSHA256Data);
322 }
323 CFReleaseNull(spkiSHA256Data);
324 }
325
326 SecPolicySetOptionsValue(policy, spkiSHA256Options[i], spkiSHA256DataArray);
327 CFReleaseNull(spkiSHA256DataArray);
328 }
329
330 return true;
331
332 errOut:
333 return false;
334 }
335
336 - (bool)addPolicy:(NSDictionary *)policyDict
337 {
338 SecPolicyRef policy = NULL;
339 NSString *policyIdentifier = [(NSDictionary *)policyDict objectForKey:kSecTrustTestPolicyOID];
340 NSDictionary *policyProperties = [(NSDictionary *)policyDict objectForKey:kSecTrustTestPolicyProperties];
341 require_string(policyIdentifier, errOut, "failed to get policy OID");
342
343 CFDictionaryRef properties = (__bridge CFDictionaryRef)policyProperties;
344 policy = SecPolicyCreateWithProperties((__bridge CFStringRef)policyIdentifier,
345 properties);
346 require_string(policy, errOut, "failed to create properties for policy OID");
347 require_string([self addThirdPartyPinningPolicyChecks:properties policy:policy], errOut, "failed to parse properties for third-party-pinning policy checks");
348 [self.policies addObject:(__bridge id)policy];
349 CFReleaseNull(policy);
350
351 return true;
352 errOut:
353 CFReleaseNull(policy);
354 return false;
355 }
356
357 - (bool)addPolicies:(id)policiesObj {
358 require_string(policiesObj, errOut,
359 "failed to get policies for test");
360
361 self.policies = [[NSMutableArray alloc] init];
362 require_string(self.policies, errOut,
363 "failed to initialize policies array");
364 if ([policiesObj isKindOfClass:[NSDictionary class]]) {
365 /* Test has only one policy */
366 require_string([self addPolicy:policiesObj], errOut, "failed to add policy");
367 } else if ([policiesObj isKindOfClass:[NSArray class]]) {
368 /* Test more than one policy */
369 [(NSArray *)policiesObj enumerateObjectsUsingBlock:^(NSDictionary *policyDict, NSUInteger idx, BOOL *stop) {
370 if (![self addPolicy:policyDict]) {
371 *stop = YES;
372 }
373 }];
374
375 require_string([(NSArray *)policiesObj count] == [self.policies count], errOut, "failed to add all policies");
376 } else {
377 require_string(false, errOut, "unexpected type for Policies value");
378 }
379
380 return true;
381
382 errOut:
383 return false;
384 }
385
386 - (bool)setAnchorsFromPlist:(id)anchorsObj {
387 NSMutableArray *anchors = [NSMutableArray array];
388 require_string(anchorsObj, errOut, "failed to get anchors for test");
389 require_string([self addCertsToArray:anchorsObj outputArray:anchors], errOut, "failed to add anchors to anchors array");
390
391 if ([anchorsObj isKindOfClass:[NSString class]]) {
392 require_string([anchors count] == 1, errOut, "failed to add all anchors");
393 } else if ([anchorsObj isKindOfClass:[NSArray class]]) {
394 require_string([anchors count] == [(NSArray *)anchorsObj count], errOut, "failed to add all anchors");
395 }
396
397 // set the anchors in the SecTrustRef
398 self.anchors = anchors;
399 return true;
400
401 errOut:
402 return false;
403 }
404
405 - (instancetype _Nullable) initWithTrustDictionary:(NSDictionary *)testDict
406 {
407 if (!(self = [super init])) {
408 return self;
409 }
410
411 NSString *majorTestName = nil, *minorTestName = nil;
412 SecTrustRef trust = NULL;
413
414 #if TARGET_OS_BRIDGE
415 /* Some of the tests don't work on bridgeOS because there is no Certificates bundle. Skip them. */
416 if([testDict[kSecTrustTestDisableBridgeOS] boolValue]) {
417 self.bridgeOSDisabled = YES;
418 }
419 #endif
420
421 /* Test certificates work by default on internal builds. We still need this to
422 * determine whether to expect failure for production devices. */
423 self.enableTestCertificates = [testDict[kSecTrustTestEnableTestCerts] boolValue];
424
425 /* Test name, for documentation purposes */
426 majorTestName = testDict[kSecTrustTestMajorTestName];
427 minorTestName = testDict[kSecTrustTestMinorTestName];
428 require_string(majorTestName && minorTestName, errOut, "Failed to create test names for test");
429 [self setMajorTestName:majorTestName minorTestName:minorTestName];
430
431 #if DEBUG
432 fprintf(stderr, "BEGIN trust creation for %s", [self.fullTestName cStringUsingEncoding:NSUTF8StringEncoding]);
433 #endif
434
435 /* Cert directory */
436 self.directory = testDict[kSecTrustTestDirectory];
437 require_string(self.directory, errOut, "No directory for test!");
438
439 /* Populate the certificates array */
440 require_quiet([self addLeafToCertificates:testDict[kSecTrustTestLeaf]], errOut);
441
442 /* Add optional intermediates to certificates array */
443 if (testDict[kSecTrustTestIntermediates]) {
444 require_quiet([self addIntermediatesToCertificates:testDict[kSecTrustTestIntermediates]], errOut);
445 }
446
447 /* Create the policies */
448 #if !TARGET_OS_BRIDGE
449 require_quiet([self addPolicies:testDict[kSecTrustTestPolicies]], errOut);
450 #else // TARGET_OS_BRIDGE
451 if (![self addPolicies:testDict[kSecTrustTestPolicies]]) {
452 /* Some policies aren't available on bridgeOS (because there is no Certificates bundle on bridgeOS).
453 * If we fail to add the policies for a disabled test, let SecTrustCreate fall back to the Basic policy.
454 * We'll skip the evaluation and other tests by honoring bridgeOSDisabled, but we need to return a
455 * TestTrustEvaluation object so that the test continues. */
456 if (self.bridgeOSDisabled) {
457 self.policies = nil;
458 } else {
459 goto errOut;
460 }
461 }
462 #endif // TARGET_OS_BRIDGE
463
464
465 /* Create the trust object */
466 require_noerr_string(SecTrustCreateWithCertificates((__bridge CFArrayRef)self.certificates,
467 (__bridge CFArrayRef)self.policies,
468 &trust),
469 errOut,
470 "failed to create trust ref");
471 self.trust = trust;
472
473 /* Optionally set anchors in trust object */
474 if (testDict[kSecTrustTestAnchors]) {
475 require_quiet([self setAnchorsFromPlist:testDict[kSecTrustTestAnchors]], errOut);
476 }
477
478 /* Set optional date in trust object */
479 if (testDict[kSecTrustTestVerifyDate]) {
480 self.verifyDate = testDict[kSecTrustTestVerifyDate];
481 }
482
483 /* Set expected results */
484 self.expectedResult = testDict[kSecTrustTestExpectedResult];
485 self.expectedChainLength = testDict[kSecTrustTestChainLength];
486
487 #if DEBUG
488 fprintf(stderr, "END trust creation for %s", [self.fullTestName cStringUsingEncoding:NSUTF8StringEncoding]);
489 #endif
490
491 return self;
492
493 errOut:
494 return nil;
495 }
496
497 - (bool)evaluateForExpectedResults:(out NSError * _Nullable __autoreleasing *)outError
498 {
499 #if TARGET_OS_BRIDGE
500 // Artificially skip tests for bridgeOS. To prevent test errors these need to be reported as a pass.
501 if (self.bridgeOSDisabled) {
502 return true;
503 }
504 #endif
505
506 if (!self.expectedResult) {
507 if (outError) {
508 NSString *errorDescription = [NSString stringWithFormat:@"Test %@: no expected results set",
509 self.fullTestName];
510 *outError = [NSError errorWithDomain:@"TrustTestsError" code:(-1)
511 userInfo:@{ NSLocalizedFailureReasonErrorKey : errorDescription}];
512 }
513 return false;
514 }
515
516 SecTrustResultType trustResult = kSecTrustResultInvalid;
517 if (errSecSuccess != SecTrustGetTrustResult(self.trust, &trustResult)) {
518 if (outError) {
519 NSString *errorDescription = [NSString stringWithFormat:@"Test %@: Failed to get trust result",
520 self.fullTestName];
521 *outError = [NSError errorWithDomain:@"TrustTestsError" code:(-2)
522 userInfo:@{ NSLocalizedFailureReasonErrorKey : errorDescription}];
523 }
524 return false;
525 }
526
527 bool result = false;
528
529 /* If we enabled test certificates on a non-internal device, expect a failure instead of success. */
530 if (self.enableTestCertificates && !SecIsInternalRelease() && ([self.expectedResult unsignedIntValue] == 4)) {
531 if (trustResult == kSecTrustResultRecoverableTrustFailure) {
532 result = true;
533 }
534 } else if (trustResult == [self.expectedResult unsignedIntValue]) {
535 result = true;
536 }
537
538 if (!result) {
539 if (outError) {
540 NSString *errorDescription = [NSString stringWithFormat:@"Test %@: Expected result %@ %s does not match actual result %u %s",
541 self.fullTestName, self.expectedResult,
542 (self.enableTestCertificates ? "for test cert" : ""),
543 trustResult,
544 SecIsInternalRelease() ? "" : "on prod device"];
545 *outError = [NSError errorWithDomain:@"TrustTestsError" code:(-3)
546 userInfo:@{ NSLocalizedFailureReasonErrorKey : errorDescription}];
547 }
548 return result;
549 }
550
551 /* expected chain length is optional, but if we have it, verify */
552 if (self.expectedChainLength && (SecTrustGetCertificateCount(self.trust) != [self.expectedChainLength longValue])) {
553 if (outError) {
554 NSString *errorDescription = [NSString stringWithFormat:@"Test %@: Expected chain length %@ does not match actual chain length %ld",
555 self.fullTestName, self.expectedChainLength, SecTrustGetCertificateCount(self.trust)];
556 *outError = [NSError errorWithDomain:@"TrustTestsError" code:(-4)
557 userInfo:@{ NSLocalizedFailureReasonErrorKey : errorDescription}];
558 }
559 return false;
560 }
561 return true;
562 }
563
564 @end
565
566 int ping_host(char *host_name)
567 {
568 struct sockaddr_in pin;
569 struct hostent *nlp_host;
570 struct in_addr addr;
571 int sd = 0;
572 int port = 80;
573 int retries = 5; // we try 5 times, then give up
574 char **h_addr_list = NULL;
575
576 while ((nlp_host=gethostbyname(host_name)) == 0 && retries--) {
577 printf("Resolve Error! (%s) %d\n", host_name, h_errno);
578 sleep(1);
579 }
580 if (nlp_host == 0) {
581 return 0;
582 }
583
584 bzero(&pin,sizeof(pin));
585 pin.sin_family=AF_INET;
586 pin.sin_addr.s_addr=htonl(INADDR_ANY);
587 h_addr_list = malloc(nlp_host->h_length * sizeof(char *));
588 memcpy(h_addr_list, nlp_host->h_addr_list, nlp_host->h_length * sizeof(char *));
589 memcpy(&addr, h_addr_list[0], sizeof(struct in_addr));
590 pin.sin_addr.s_addr=addr.s_addr;
591 pin.sin_port=htons(port);
592
593 sd=socket(AF_INET,SOCK_STREAM,0);
594
595 if (connect(sd,(struct sockaddr*)&pin,sizeof(pin)) == -1) {
596 printf("connect error! (%s) %d\n", host_name, errno);
597 close(sd);
598 free(h_addr_list);
599 return 0;
600 }
601 close(sd);
602 free(h_addr_list);
603 return 1;
604 }