コード例 #1
0
ファイル: keychain.c プロジェクト: fcheung/keychain_c
static VALUE rb_keychain_status(VALUE self){
  UInt32 status;
  SecKeychainRef keychain=NULL;
  Data_Get_Struct(self, struct OpaqueSecKeychainRef, keychain);
  OSStatus result = SecKeychainGetStatus(keychain, &status);
  CheckOSStatusOrRaise(result);
  return UINT2NUM(status);
}
コード例 #2
0
ファイル: main.c プロジェクト: pnc/splitring
SecKeychainRef SROpenKeychain(char* path) {
  SecKeychainRef keychain = NULL;
  OSStatus status = SecKeychainOpen(path, &keychain);
  SecKeychainStatus keychainStatus = 0;
  status = SecKeychainGetStatus(keychain, &keychainStatus);
  if (status == 0) {
  } else {
    fprintf(stderr, "Unable to open keychain at path %s: ", path);
    SRHandleError(status, false);
    exit(EX_IOERR);
  }
  return keychain;
}
コード例 #3
0
/* 
 * Returns true if we are to allow/trust the specified
 * cert as a PKINIT-only anchor.
 */
static bool tpCheckPkinitServerCert(
	TPCertGroup &certGroup)
{
	/* 
	 * Basic requirement: exactly one cert, self-signed.
	 * The numCerts == 1 requirement might change...
	 */
	unsigned numCerts = certGroup.numCerts();
	if(numCerts != 1) {
		tpDebug("tpCheckPkinitServerCert: too many certs");
		return false;
	}
	/* end of chain... */
	TPCertInfo *theCert = certGroup.certAtIndex(numCerts - 1);
	if(!theCert->isSelfSigned()) {
		tpDebug("tpCheckPkinitServerCert: 1 cert, not self-signed");
		return false;
	}
	const CSSM_DATA *subjectName = theCert->subjectName();
	
	/* 
	 * Open the magic keychain.
	 * We're going up and over the Sec layer here, not generally 
	 * kosher, but this is a temp hack.
	 */
	OSStatus ortn;
	SecKeychainRef kcRef = NULL;
	string fullPathName;
	const char *homeDir = getenv("HOME");
	if (homeDir == NULL)
	{
		// If $HOME is unset get the current user's home directory
		// from the passwd file.
		uid_t uid = geteuid();
		if (!uid) uid = getuid();
		struct passwd *pw = getpwuid(uid);
		if (!pw) {
			return false;
		}
		homeDir = pw->pw_dir;
	}
	fullPathName = homeDir;
	fullPathName += "/Library/Application Support/PKINIT/TrustedServers.keychain";
	ortn = SecKeychainOpen(fullPathName.c_str(), &kcRef);
	if(ortn) {
		tpDebug("tpCheckPkinitServerCert: keychain not found (1)");
		return false;
	}
	/* subsequent errors to errOut: */
	
	bool ourRtn = false;
	SecKeychainStatus kcStatus;
	CSSM_DATA_PTR subjSerial = NULL;
	CSSM_RETURN crtn;
	SecKeychainSearchRef		srchRef = NULL;
	SecKeychainAttributeList	attrList;
	SecKeychainAttribute		attrs[2];
	SecKeychainItemRef			foundItem = NULL;
	
	ortn = SecKeychainGetStatus(kcRef, &kcStatus);
	if(ortn) {
		tpDebug("tpCheckPkinitServerCert: keychain not found (2)");
		goto errOut;
	}
	
	/*
	 * We already have this cert's normalized name; get its
	 * serial number.
	 */
	crtn = theCert->fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial);
	if(crtn) {
		/* should never happen */
		tpDebug("tpCheckPkinitServerCert: error fetching serial number");
		goto errOut;
	}
	
	attrs[0].tag    = kSecSubjectItemAttr;
	attrs[0].length = subjectName->Length;
	attrs[0].data   = subjectName->Data;
	attrs[1].tag    = kSecSerialNumberItemAttr;
	attrs[1].length = subjSerial->Length;
	attrs[1].data   = subjSerial->Data;
	attrList.count  = 2;
	attrList.attr   = attrs;
	
	ortn = SecKeychainSearchCreateFromAttributes(kcRef,
		kSecCertificateItemClass,
		&attrList,
		&srchRef);
	if(ortn) {
		tpDebug("tpCheckPkinitServerCert: search failure");
		goto errOut;
	}
	for(;;) {
		ortn = SecKeychainSearchCopyNext(srchRef, &foundItem);
		if(ortn) {
			tpDebug("tpCheckPkinitServerCert: end search");
			break;
		}
		
		/* found a matching cert; do byte-for-byte compare */
		CSSM_DATA certData;
		ortn = SecCertificateGetData((SecCertificateRef)foundItem, &certData);
		if(ortn) {
			tpDebug("tpCheckPkinitServerCert: SecCertificateGetData failure");
			continue;
		}
		if(tpCompareCssmData(&certData, theCert->itemData())){
			tpDebug("tpCheckPkinitServerCert: FOUND CERT");
			ourRtn = true;
			break;
		}
		tpDebug("tpCheckPkinitServerCert: skipping matching cert");
		CFRelease(foundItem);
		foundItem = NULL;
	}
errOut:
	CFRELEASE(kcRef);
	CFRELEASE(srchRef);
	CFRELEASE(foundItem);
	if(subjSerial != NULL) {
		theCert->freeField(&CSSMOID_X509V1SerialNumber, subjSerial);
	}
	return ourRtn;
}
コード例 #4
0
/*
 * Given an open keychain, find a SecIdentityRef and munge it into
 * a CFArrayRef required by SSLSetCertificate().
 */
CFArrayRef sslKcRefToCertArray(
	SecKeychainRef		kcRef,
	bool                encryptOnly,
	bool                completeCertChain,
	const char			*trustedAnchorFile)
{
	/* quick check to make sure the keychain exists */
	SecKeychainStatus kcStat;
	OSStatus ortn = SecKeychainGetStatus(kcRef, &kcStat);
	if(ortn) {
		printSslErrStr("SecKeychainGetStatus", ortn);
		printf("Can not open keychain. Aborting.\n");
		return nil;
	}
	
	/*
	 * Search for "any" identity matching specified key use; 
	 * in this app, we expect there to be exactly one. 
	 */
	SecIdentitySearchRef srchRef = nil;
	ortn = SecIdentitySearchCreate(kcRef, 
		encryptOnly ? CSSM_KEYUSE_DECRYPT : CSSM_KEYUSE_SIGN,
		&srchRef);
	if(ortn) {
		printf("SecIdentitySearchCreate returned %d.\n", (int)ortn);
		printf("Cannot find signing key in keychain. Aborting.\n");
		return nil;
	}
	SecIdentityRef identity = nil;
	ortn = SecIdentitySearchCopyNext(srchRef, &identity);
	if(ortn) {
		printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn);
		printf("Cannot find signing key in keychain. Aborting.\n");
		return nil;
	}
	if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
		printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
		return nil;
	}

	/* 
	 * Found one. 
	 */
	if(completeCertChain) {
		/* 
		 * Place it and the other certs needed to verify it -
		 * up to but not including the root - in a CFArray.
		 */
		SecCertificateRef anchorCert = NULL;
		if(trustedAnchorFile) {
			ortn = sslReadAnchor(trustedAnchorFile, &anchorCert);
			if(ortn) {
				printf("***Error reading anchor file\n");
			}
		}
		CFArrayRef ca;
		ortn = sslCompleteCertChain(identity, anchorCert, false, &ca);
		if(anchorCert) {
			CFRelease(anchorCert);
		}
		return ca;
	}
	else {
		/* simple case, just this one identity */
		CFArrayRef ca = CFArrayCreate(NULL,
			(const void **)&identity,
			1,
			NULL);
		if(ca == nil) {
			printf("CFArrayCreate error\n");
		}
		return ca;
	}
}
コード例 #5
0
static void tests(void)
{
	char *home = getenv("HOME");
	char kcname1[256], kcname2[256];
	SecKeychainStatus status1, status2;

	if (!home || strlen(home) > 200)
		plan_skip_all("home too big");

	sprintf(kcname1, "%s/kctests/kc1/kc1", home);
	SecKeychainRef kc1 = NULL, kc2 = NULL;
    kc1 = createNewKeychainAt(kcname1, "test");

	ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status");
	is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus,
		"status unlocked readable writable");
	ok_status(SecKeychainLock(kc1), "SecKeychainLock kc1");
	ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status");
	TODO: {
		todo("<rdar://problem/2668794> KeychainImpl::status() returns "
			"incorrect status (always writable?)");

		is(status1, kSecReadPermStatus|kSecWritePermStatus,
			"status (locked) readable writable");
	}

	/* Make keychain non writable. */
	char kcdir1[256];
	sprintf(kcdir1, "%s/kctests/kc1", home);
	ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555");

	ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status");
	is(status1, kSecReadPermStatus, "status (locked) readable");
	ok_status(SecKeychainUnlock(kc1, 4, "test", TRUE), "SecKeychainLock kc1");
	ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status");
	TODO: {
		todo("<rdar://problem/2668794> KeychainImpl::status() returns "
			"incorrect status (always writable?)");

		is(status1, kSecUnlockStateStatus|kSecReadPermStatus,
			"status unlocked readable");
	}

	/* Reopen the keychain. */
	CFRelease(kc1);
	ok_status(SecKeychainOpen(kcname1, &kc1), "SecKeychainOpen kc1");

	ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status");
	TODO: {
		todo("<rdar://problem/2668794> KeychainImpl::status() returns "
			"incorrect status (always writable?)");

		is(status1, kSecUnlockStateStatus|kSecReadPermStatus,
			"status unlocked readable");
	}

	sprintf(kcname2, "%s/kctests/kc2/kc2", home);
    kc2 = createNewKeychainAt(kcname2, "test");
	ok_unix(chmod(kcname2, 0444), "chmod kc2 0444");
	ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status");
	is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus,
		"status unlocked readable writable");

	/* Reopen the keychain. */
	CFRelease(kc2);
	ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2");

	ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status");
	is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus,
		"status unlocked readable writable");

	/* Restore dir to writable so cleanup code will work ok. */
	ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755");
    ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName);
	CFRelease(kc1);
    ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName);
	CFRelease(kc2);

	bool testWithFreshlyCreatedKeychain = true;
	SecKeychainRef keychain = createNewKeychain("test", "test");
	ok_status(SecKeychainLock(keychain), "SecKeychainLock");

	do {
		SecKeychainStatus keychainStatus = 0;
		is_status(SecKeychainUnlock(keychain, 0, NULL, true), -25293, "SecKeychainUnlock with NULL password (incorrect)");
		ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus");
		is( (keychainStatus & kSecUnlockStateStatus), 0, "Check it's not unlocked");

		keychainStatus = 0;
		ok_status(SecKeychainUnlock(keychain, strlen("test"), "test", true), "SecKeychainUnlock with correct password");
		ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus");
		is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked");
		
		ok_status(SecKeychainLock(keychain), "SecKeychainLock");

		if (testWithFreshlyCreatedKeychain)
		{
        CFRelease(keychain);
			testWithFreshlyCreatedKeychain = false;
			ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen");
		}
        else {
			testWithFreshlyCreatedKeychain = true;

            ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
            CFReleaseNull(keychain);
        }
		
	}
	while(!testWithFreshlyCreatedKeychain);

}