Opened 22 months ago

Last modified 3 weeks ago

#66749 new enhancement

Add SecTrustEvaluateWithError to allow Go binaries built with 1.19+ to run on older systems

Reported by: krackers Owned by:
Priority: Normal Milestone:
Component: ports Version:
Keywords: Cc: cjones051073 (Chris Jones), kencu (Ken), RobK88
Port: legacy-support

Description

Since the change https://go-review.googlesource.com/c/go/+/353132 Go now calls into libSecurity's SecTrustEvaluateWithError for certificate validation. As a result, even with a legacySupport dylib injected to shim the missing libc functions Go needs, because SecTrustEvaluateWithError is present only on 10.14+, binaries will still refuse to run on older versions.

Older versions do have a SecTrustEvaluate which does the same validation but returns its output in a slightly different format. Hence it should not be too hard to write a wrapper.

This would also resolve https://trac.macports.org/ticket/65178

Change History (4)

comment:1 Changed 22 months ago by jmroot (Joshua Root)

Cc: cjones051073 kencu added

comment:2 Changed 22 months ago by krackers

I think something like the below should work.

CFStringRef getStringForResultType(SecTrustResultType resultType) {
	switch (resultType) {
		case kSecTrustResultInvalid: return CFSTR("Error evaluating certificate");
		case kSecTrustResultDeny: return CFSTR("User specified to deny trust");
		case kSecTrustResultUnspecified: return CFSTR("Rejected Certificate");
		case kSecTrustResultRecoverableTrustFailure : return CFSTR("Rejected Certificate");
		case kSecTrustResultFatalTrustFailure :return CFSTR("Bad Certificate");
		case kSecTrustResultOtherError: return CFSTR("Error evaluating certificate");
		case kSecTrustResultProceed: return CFSTR("Proceed");
		default: return CFSTR("Unknown");
	}
	return CFSTR("Unknown");
}

bool CustomSecTrustEvaluateWithError(SecTrustRef trust, CFErrorRef  *error) {
	SecTrustResultType trustResult = kSecTrustResultInvalid;
	OSStatus status = SecTrustEvaluate(trust, &trustResult);
	if (status == errSecSuccess && (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified)) {
		if (error) {
			*error = NULL;
		}
		return true;
	}
        if (error)
	    *error = CFErrorCreate(kCFAllocatorDefault, getStringForResultType(trustResult), 0, NULL);
	return false;
}

This may not work for any application that does logic based on the actual error code (I briefly looked and it seemed tricky to get this via private APIs). But for go at least, this should work.

Last edited 22 months ago by krackers (previous) (diff)

comment:3 Changed 14 months ago by RobK88

Cc: RobK88 added

comment:4 Changed 3 weeks ago by ok-coder1 (okcoder1)

Any PR on this created yet?

Note: See TracTickets for help on using tickets.